Java에서 스레드를 올바르게 중지하려면 어떻게 해야 합니다.
자바에서 스레드를 올바르게 정지하기 위한 솔루션이 필요합니다.
있다IndexProcessor
Runnable " " " run run run" :
public class IndexProcessor implements Runnable {
private static final Logger LOGGER = LoggerFactory.getLogger(IndexProcessor.class);
@Override
public void run() {
boolean run = true;
while (run) {
try {
LOGGER.debug("Sleeping...");
Thread.sleep((long) 15000);
LOGGER.debug("Processing");
} catch (InterruptedException e) {
LOGGER.error("Exception", e);
run = false;
}
}
}
}
제가 있는 게 있어요.ServletContextListener
"CHANGE: "CHANGE: "CHANGE: " 。
public class SearchEngineContextListener implements ServletContextListener {
private static final Logger LOGGER = LoggerFactory.getLogger(SearchEngineContextListener.class);
private Thread thread = null;
@Override
public void contextInitialized(ServletContextEvent event) {
thread = new Thread(new IndexProcessor());
LOGGER.debug("Starting thread: " + thread);
thread.start();
LOGGER.debug("Background process successfully started.");
}
@Override
public void contextDestroyed(ServletContextEvent event) {
LOGGER.debug("Stopping thread: " + thread);
if (thread != null) {
thread.interrupt();
LOGGER.debug("Thread successfully stopped.");
}
}
}
단, Tomcat을 셧다운하면 IndexProcessor 클래스에서 예외가 발생합니다.
2012-06-09 17:04:50,671 [Thread-3] ERROR IndexProcessor Exception
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at lt.ccl.searchengine.processor.IndexProcessor.run(IndexProcessor.java:22)
at java.lang.Thread.run(Unknown Source)
JDK 1.6을 사용하고 있습니다.질문은 다음과 같습니다.
어떻게 하면 스레드를 멈추고 예외를 던지지 않을 수 있을까요?
추신: 사용하고 싶지 않습니다..stop();
권장되지 않기 때문에 메서드를 사용합니다.
「」를 사용합니다.Thread.interrupt()
완벽하게 받아들일 수 있는 방법이라고 생각합니다.실제로 위에서 제시한 플래그보다 선호될 수 있습니다. 가능한(「」등)에입니다.Thread.sleep
또는 java.nio 채널 운영 사용)을 통해 이러한 운영에서 즉시 벗어날 수 있습니다.
플래그를 사용할 경우 차단 작업이 완료될 때까지 기다려야 플래그를 확인할 수 있습니다.표준적인 것을 경우도 .InputStream
/OutputStream
방해할 수 없습니다.
이 경우 스레드가 중단되어도 입출력이 중단되지는 않지만 코드로 쉽게 실행할 수 있습니다(또한 안전하게 정지 및 청소할 수 있는 전략적 지점에서 이를 수행해야 합니다).
if (Thread.currentThread().isInterrupted()) {
// cleanup and stop execution
// for example a break in a loop
}
말씀드렸듯이 가장 큰 장점은Thread.interrupt()
중단 가능한 콜에서 즉시 벗어날 수 있다는 것입니다.을 사용하다
서서 IndexProcessor
합니다.run
이치노
는 이 합니다.join()
스레드 위에 올려놓고 끝날 때까지 기다립니다.
플래그가 스레드 세이프인지 확인하려면 휘발성 변수를 사용하거나 플래그로 사용되는 변수와 동기화된 getter 및 setter 메서드를 사용합니다.
public class IndexProcessor implements Runnable {
private static final Logger LOGGER = LoggerFactory.getLogger(IndexProcessor.class);
private volatile boolean running = true;
public void terminate() {
running = false;
}
@Override
public void run() {
while (running) {
try {
LOGGER.debug("Sleeping...");
Thread.sleep((long) 15000);
LOGGER.debug("Processing");
} catch (InterruptedException e) {
LOGGER.error("Exception", e);
running = false;
}
}
}
}
ㅇㅇㅇㅇ에서SearchEngineContextListener
:
public class SearchEngineContextListener implements ServletContextListener {
private static final Logger LOGGER = LoggerFactory.getLogger(SearchEngineContextListener.class);
private Thread thread = null;
private IndexProcessor runnable = null;
@Override
public void contextInitialized(ServletContextEvent event) {
runnable = new IndexProcessor();
thread = new Thread(runnable);
LOGGER.debug("Starting thread: " + thread);
thread.start();
LOGGER.debug("Background process successfully started.");
}
@Override
public void contextDestroyed(ServletContextEvent event) {
LOGGER.debug("Stopping thread: " + thread);
if (thread != null) {
runnable.terminate();
thread.join();
LOGGER.debug("Thread successfully stopped.");
}
}
}
간단한 답변:스레드는 다음 두 가지 일반적인 방법 중 하나로 내부적으로 정지할 수 있습니다.
- run 메서드는 리턴 서브루틴에 히트합니다.
- 실행 메서드가 종료되고 암묵적으로 반환됩니다.
또한 외부에서 스레드를 중지할 수도 있습니다.
- ★★
system.exit
전체가 됩니다). - " " 를 합니다.
interrupt()
메서드 * - 합니다(예: 동작하는 것 같음).
kill()
또는stop()
)
*: 이것은 스레드를 정지시키는 것으로 기대됩니다.그러나 이 경우 스레드가 실제로 수행하는 작업은 전적으로 스레드 구현을 만들 때 개발자가 작성한 내용에 달려 있습니다.
실행 방식의 구현에서 흔히 볼 수 있는 패턴은while(boolean){}
여기서 부울은 보통 이름이 붙은 것입니다.isRunning
스레드 클래스의 멤버 변수이며 휘발성이 높으며 일반적으로 다른 스레드에서 setter 메서드(예: setter method)로 액세스할 수 있습니다.kill() { isRunnable=false; }
이러한 서브루틴은 스레드가 종료하기 전에 보유하고 있는 리소스를 해방할 수 있도록 하기 때문에 좋습니다.
스레드는 항상 플래그를 체크하여 종료해야 합니다.run()
루프(있는 경우)
스레드는 다음과 같습니다.
public class IndexProcessor implements Runnable {
private static final Logger LOGGER = LoggerFactory.getLogger(IndexProcessor.class);
private volatile boolean execute;
@Override
public void run() {
this.execute = true;
while (this.execute) {
try {
LOGGER.debug("Sleeping...");
Thread.sleep((long) 15000);
LOGGER.debug("Processing");
} catch (InterruptedException e) {
LOGGER.error("Exception", e);
this.execute = false;
}
}
}
public void stopExecuting() {
this.execute = false;
}
}
그런 다음 콜을 통해 스레드를 종료할 수 있습니다.thread.stopExecuting()
이렇게 하면 실이 깨끗하게 끝나지만 (수면 때문에) 최대 15초 걸립니다.스레드를 호출할 수 있습니다.interrupt()는 긴급한 경우에는 플래그를 항상 확인하는 것이 좋습니다.
15초 동안 기다리지 않으려면 다음과 같이 sleeve를 분할할 수 있습니다.
...
try {
LOGGER.debug("Sleeping...");
for (int i = 0; (i < 150) && this.execute; i++) {
Thread.sleep((long) 100);
}
LOGGER.debug("Processing");
} catch (InterruptedException e) {
...
일반적으로 스레드는 중단되면 종료됩니다.그럼 네이티브 부울을 사용하면 어떨까요?isInterrupted()를 시도합니다.
Thread t = new Thread(new Runnable(){
@Override
public void run() {
while(!Thread.currentThread().isInterrupted()){
// do stuff
}
}});
t.start();
// Sleep a second, and then interrupt
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
t.interrupt();
ref- 어떻게 실을 끊을 수 있나요? stop()을 사용하지 않음;
원하는 스레드 동기화용CountDownLatch
프로세스가 완료될 때까지 스레드가 대기할 수 있습니다.이 경우 워커 클래스는 다음과 같이 설정됩니다.CountDownLatch
츠키노의 콜await
이 될 까지 차단합니다.는 0이 되기 때문입니다.countDown
했습니다.하면 지정된 까지 기다릴 스레드를 할 수 있습니다.
public class IndexProcessor implements Runnable {
private static final Logger LOGGER = LoggerFactory.getLogger(IndexProcessor.class);
private final CountDownLatch countdownlatch;
public IndexProcessor(CountDownLatch countdownlatch) {
this.countdownlatch = countdownlatch;
}
public void run() {
try {
while (!countdownlatch.await(15000, TimeUnit.MILLISECONDS)) {
LOGGER.debug("Processing...");
}
} catch (InterruptedException e) {
LOGGER.error("Exception", e);
run = false;
}
}
}
스레드의 을 countDown으로 합니다.CountDownLatch
★★★★★★★★★★★★★★★★★」join
「 」의 「 」의 「 」
public class SearchEngineContextListener implements ServletContextListener {
private static final Logger LOGGER = LoggerFactory.getLogger(SearchEngineContextListener.class);
private Thread thread = null;
private IndexProcessor runnable = null;
private CountDownLatch countdownLatch = null;
@Override
public void contextInitialized(ServletContextEvent event) {
countdownLatch = new CountDownLatch(1);
Thread thread = new Thread(new IndexProcessor(countdownLatch));
LOGGER.debug("Starting thread: " + thread);
thread.start();
LOGGER.debug("Background process successfully started.");
}
@Override
public void contextDestroyed(ServletContextEvent event) {
LOGGER.debug("Stopping thread: " + thread);
if (countdownLatch != null)
{
countdownLatch.countDown();
}
if (thread != null) {
try {
thread.join();
} catch (InterruptedException e) {
LOGGER.error("Exception", e);
}
LOGGER.debug("Thread successfully stopped.");
}
}
}
몇 가지 보충 정보입니다.Java 문서에는 플래그와 인터럽트가 모두 권장됩니다.
https://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html
private volatile Thread blinker;
public void stop() {
blinker = null;
}
public void run() {
Thread thisThread = Thread.currentThread();
while (blinker == thisThread) {
try {
Thread.sleep(interval);
} catch (InterruptedException e){
}
repaint();
}
}
의 경우 ( )를 합니다.Thread.interrupt
public void stop() {
Thread moribund = waiter;
waiter = null;
moribund.interrupt();
}
Android에서 작업을 중단하지 않았기 때문에 이 방법을 사용하여 완벽하게 작동합니다.
boolean shouldCheckUpdates = true;
private void startupCheckForUpdatesEveryFewSeconds() {
threadCheckChat = new Thread(new CheckUpdates());
threadCheckChat.start();
}
private class CheckUpdates implements Runnable{
public void run() {
while (shouldCheckUpdates){
System.out.println("Do your thing here");
}
}
}
public void stop(){
shouldCheckUpdates = false;
}
언급URL : https://stackoverflow.com/questions/10961714/how-to-properly-stop-the-thread-in-java
'programing' 카테고리의 다른 글
Vue 인스턴스에서 글로벌 믹스인 메서드를 사용하는 방법 (0) | 2022.07.03 |
---|---|
Vuex의 확산 연산자가 babel로 올바르게 컴파일되지 않아 모듈 구축에 계속 실패함 (0) | 2022.07.03 |
vue 2에서 구성 요소의 루트 요소에 대한 이벤트를 테스트하는 방법 (0) | 2022.07.02 |
Java: 날짜에서 월 정수 가져오기 (0) | 2022.07.02 |
Vue setup() 메서드로 Vuex 스토어에 액세스하는 방법 (0) | 2022.07.02 |