code

Java 스레드를 정상적으로 중지하는 방법은 무엇입니까?

codestyles 2020. 11. 18. 09:07
반응형

Java 스레드를 정상적으로 중지하는 방법은 무엇입니까?


스레드를 작성했는데 실행하는 데 너무 많은 시간이 걸리고 완전히 완료되지 않은 것 같습니다. 스레드를 우아하게 중지하고 싶습니다. 도움이 필요하세요?


좋은의 그것을 할 방법은 것입니다 run()a로 보호 스레드의 boolean변수를과하도록 설정 true하면, 같은 것을 중지 할 때 외부에서 :

class MyThread extends Thread
{
  volatile boolean finished = false;

  public void stopMe()
  {
    finished = true;
  }

  public void run()
  {
    while (!finished)
    {
      //do dirty work
    }
  }
}

옛날에 stop()방법이 존재했지만 문서에 나와있는대로

이 방법은 본질적으로 안전하지 않습니다. Thread.stop으로 스레드를 중지하면 잠긴 모든 모니터의 잠금이 해제됩니다 (스택 위로 전파되는 확인되지 않은 ThreadDeath 예외의 자연스러운 결과로). 이러한 모니터에 의해 이전에 보호 된 개체가 일관성없는 상태에있는 경우 손상된 개체가 다른 스레드에 표시되어 잠재적으로 임의 동작이 발생할 수 있습니다.

그래서 경비원이 있어야합니다 ..


스레드를 중지하기 위해 플래그를 사용하는 것의 나쁜 점은 스레드가 대기 중이거나 대기 중이면 대기 / 수면이 완료 될 때까지 기다려야한다는 것입니다. 스레드에서 인터럽트 메소드를 호출하면 InterruptedException과 함께 wait 또는 sleep 호출이 종료됩니다.

(플래그 접근 방식에 대한 두 번째 나쁜 부분은 대부분의 사소한 코드가 java.util.concurrent와 같은 라이브러리를 사용한다는 것입니다. 클래스는 특히 인터럽트를 사용하여 취소하도록 설계되었습니다. 전달 된 작업에서 손으로 굴린 플래그를 사용하려고합니다. Executir로 들어가는 것은 어색 할 것입니다.)

interrupt () 호출은 또한 종료 여부를 확인하기위한 플래그로 사용할 수있는 인터럽트 된 속성을 설정합니다 (스레드가 대기 중이거나 휴면 상태가 아닌 경우).

스레드의 실행 메소드를 작성하여 스레드가 수행하는 루프 로직 외부에서 InterruptedException이 포착되도록하거나 루프 내에서 예외를 포착하고 예외를 발생시키는 호출에 가깝게 할 수 있습니다. InterruptedException은 스레드가 인터럽트되었다는 사실을 추적하지 않도록합니다. 인터럽트 된 스레드는 여전히 제어를 유지하고 자체 조건으로 처리를 완료 할 수 있습니다.

어떤 이유로 중간에 수면이있는 증분 작업을 수행하는 작업자 스레드를 작성하고 해당 증분에 대한 나머지 작업을 수행하지 않고 처리를 종료하기 위해 수면을 종료하고 싶지 않다고 가정 해 보겠습니다. 증분 사이에 있으면 종료됩니다.

class MyThread extends Thread
{
    public void run()
    {
        while (!Thread.currentThread().isInterrupted())
        {
            doFirstPartOfIncrement();
            try {
                Thread.sleep(10000L);
            } catch (InterruptedException e) {
                // restore interrupt flag
                Thread.currentThread().interrupt();
            }
            doSecondPartOfIncrement();
        }
    }
}

다음은 예제 코드를 포함하여 유사한 질문에 대한 답변입니다.


다른 스레드에서 스레드를 죽이면 안됩니다. 상당히 나쁜 습관으로 간주됩니다. 그러나 여러 가지 방법이 있습니다. return스레드의 run메서드 에서 문을 사용할 수 있습니다 . 또는 스레드가 이미 중단되었는지 확인한 다음 작업을 취소 할 수 있습니다. Fe :

while (!isInterrupted()) { 
  // doStuff
}

stop어딘가에 휘발성 부울을 만드십시오 . 그런 다음 스레드에서 실행되는 코드에서 정기적으로

 if (stop) // end gracefully by breaking out of loop or whatever

스레드를 중지하려면로 설정 stop하십시오 true.

이런 식으로 수동으로해야한다고 생각합니다. 결국, 스레드에서 실행되는 코드 만이 우아하고 비정상적인 것을 알 수 있습니다.


스레드에 중지 메시지를 보내야하며 메시지가 수신되면 스레드 자체가 조치를 취해야합니다. 장기 실행 작업이 루프 내부에 있으면 매우 쉽습니다.

public class StoppableThread extends Thread {

   private volatile boolean stop = false;

   public void stopGracefully() {
     stop = true;
   }

   public void run() {
     boolean finished = false;
     while (!stop && !finished) {
       // long running action - finished will be true once work is done
     }
   }
}

For a thread to stop itself, no one seems to have mentioned (mis)using exception:

abstract class SelfStoppingThread extends Thread {

    @Override
    public final void run() {
        try {
            doRun();
        } catch (final Stop stop) {
            //optional logging
        }
    }

    abstract void doRun();

    protected final void stopSelf() {
        throw new Stop();
    }

    private static final class Stop extends RuntimeException {};

}

A subclass just need to override doRun() normally as you would with a Thread, and call stopSelf() whenever it feels like it wants to stop. IMO it feels cleaner than using a flag in a while loop.

참고URL : https://stackoverflow.com/questions/3194545/how-to-stop-a-java-thread-gracefully

반응형