Java 동시성-인터럽트 정책

Aug 26 2020

저는 Java Concurrency in Practice를 읽고 있습니다. 장의 중단 정책 섹션에서

취소 및 종료

언급

작업은 특정 인터럽트 정책이있는 서비스 내에서 실행되도록 명시 적으로 설계되지 않은 경우 실행중인 스레드의 인터럽트 정책에 대해 어떤 것도 가정해서는 안됩니다. 작업이 중단을 취소로 해석하든 중단시 다른 조치를 취하 든, 실행중인 스레드의 중단 상태를 유지하도록주의해야합니다. InterruptedException을 호출자에게 전파하지 않을 경우 InterruptionException : Thread.currentThread (). interrupt ()를 포착 한 후 중단 상태를 복원해야합니다.

그래서 나는 이해하기 위해 목록 샘플을 가지고 놀았습니다. 그러나 나는 출력과 혼동된다.

PrimeProducer

public class CorrectPrimeProducer extends Thread {

    private final BlockingQueue<BigInteger> queue;

    public CorrectPrimeProducer(BlockingQueue<BigInteger> queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        try {
            System.out.println(Thread.currentThread().getName()+" interrupt status in producer:" + Thread.currentThread().isInterrupted());
            BigInteger p = BigInteger.ONE;
            while (!Thread.currentThread().isInterrupted()) {
                queue.put(p = p.nextProbablePrime());
            }
        } catch (InterruptedException e) {
            /* Allow thread to exit */
            Thread.currentThread().interrupt();
            System.out.println(Thread.currentThread().getName()+" interrupt status in producer catch:" + Thread.currentThread().isInterrupted());
        }
    }
}

주요 방법 ##

public static void main(String[] args) throws InterruptedException {
        BlockingQueue<BigInteger> primes = new LinkedBlockingQueue<>();
        CorrectPrimeProducer generator = new CorrectPrimeProducer(primes);
        generator.start();
        try {
            while (needMorePrimes()) {
                consume(primes.take());
            }
        } finally {
            generator.interrupt();
        }
        TimeUnit.SECONDS.sleep(5);
        System.out.println(generator.getName()+" interrupt status in main:"+generator.isInterrupted());
    }

    //do something
    private static void consume(BigInteger take) {
        System.out.println(take);
    }

    private static int counter = 1;

    private static boolean needMorePrimes() {
        counter++;
        if(counter == 10){
// after counter reaches 10 return false
            return false;
        }
        return true; 
    }

산출:

// when TimeUnit.SECONDS.sleep(5); in main class is not commented

Thread-0 interrupt status in producer:false
2
3
5
7
11
13
17
19
Thread-0 interrupt status in producer catch:true
Thread-0 interrupt status in main:false
//When TimeUnit.SECONDS.sleep(5); in main class is commented
Thread-0 interrupt status in producer:false
2
3
5
7
11
13
17
19
Thread-0 interrupt status in main:true
Thread-0 interrupt status in producer catch:true

질문

  1. 메인 클래스의 메인 스레드에 TimeUnit.SECONDS.sleep (5)를 추가하면됩니다. 실행중인 스레드 (즉, 생성기) 인터럽트 상태가 재설정되고 있습니다. TimeUnit.SECONDS.sleep (5) 메서드에 주석을 달면이 경우 인터럽트 상태가 유지됩니다. 왜 이런 일이 일어나고 어떻게됩니까?

  2. 책에서 언급 된 스레드는 소유자에 의해서만 중단되어야합니다. 위의 예에서 소유자는 누구입니까? 나는 그것의 주요 메소드 스레드를 생각한다.

답변

1 Joni Aug 26 2020 at 04:25

추가 TimeUnit.SECONDS.sleep(5)하면 스레드가 종료 될 수있는 충분한 시간이 주어집니다.

스레드가 종료되면 인터럽트 플래그가 지워집니다.

이것은 사양에 문서화되어 있지 않지만 일어나는 일입니다. 예를 들어이 버그 보고서를 참조하십시오 .

여기에 위반되는 사양이 없으므로 버그가 아닌 개선 요청으로 만들었습니다. 분명히 사양의 부족은 버그입니다. 인터럽트 상태가 VM에 저장되고 스레드가 종료되면 더 이상 존재하지 않는다는 사실을 처리하기 위해 의도적으로 "종료 후 인터럽트가 영향을 미치지 않음"을 지정했습니다. 그러나 우리는 Thread.isInterrupted 사양에 반영하는 것을 무시했습니다.

extra가 없으면 sleep이론적 으로 경쟁 조건이 있기 때문에 truefalse인터럽트 상태를 모두 볼 수 있다고 생각 하지만 true스레드 스케줄링 덕분에 훨씬 더 많이 볼 수 있습니다 . throw되는 예외와 catch 블록에서 복원되는 인터럽트 상태 사이의 인터럽트 상태가 거짓 인 시간 창은 매우 작습니다.

2 michalk Aug 26 2020 at 03:49

메인 클래스의 메인 스레드에 TimeUnit.SECONDS.sleep (5)를 추가하면됩니다. 실행중인 스레드 (즉, 생성기) 인터럽트 상태가 재설정되고 있습니다. TimeUnit.SECONDS.sleep (5) 메서드에 주석을 달면이 경우 인터럽트 상태가 유지됩니다. 왜 이런 일이 일어나고 어떻게됩니까?

메인 스레드와 CorrectPrimeProducer메인 스레드가 상태를 인쇄 할 때 (블로킹 큐와는 별개로) 동기화 메커니즘을 사용하지 CorrectPrimeProducer않고 있습니다. catch따라서 블록 명령 을 수행하여 인터럽트 된 상태를 아직 보존하지 않았을 수 있으므로 false결과 를 얻습니다 .

sleep메인에 추가 하면 메인 스레드가 상태를 인쇄하기 전에 블록 명령 을 호출 Thread하여 CorrectPrimeProducer스레드가 인터럽트 상태를 유지할 가능성을 높일 catch수 있습니다. 그것이 인쇄하는 이유 true입니다.

책에서 언급 된 스레드는 소유자에 의해서만 중단되어야합니다. 위의 예에서 소유자는 누구입니까? 나는 그것의 주요 메소드 스레드를 생각한다.

이 경우 사용자는 스레드의 소유자 (소유자는 스레드를 생성하는 코드) CorrectPrimeProducer이므로 인터럽트의 의미를 결정합니다. 예를 들어 중단 된 경우 다시 만들 수 있습니다 (예 Thread: 기본적으로 Java 스레드 풀의 s에 대해 발생 ).