catch InterruptException 블록에서 Thread.currentThread.interrupt ()를 호출하는 이유는 무엇입니까?


답변:


160

이것은 상태유지 하기 위해 수행됩니다 .

당신이 InterruptException그것을 잡아 삼킬 때, 당신은 본질적으로 더 높은 수준의 메소드 / 스레드 그룹이 인터럽트를 알지 못하게합니다. 문제가 발생할 수 있습니다.

를 호출 Thread.currentThread().interrupt()하면 스레드의 인터럽트 플래그를 설정하므로 높은 수준의 인터럽트 핸들러가이를 감지하여 적절하게 처리 할 수 ​​있습니다.

실제로 Java Concurrency는 이에 대한 자세한 내용은 7.1.3 장 : 인터럽트에 응답 에서 설명합니다 . 규칙은 다음과 같습니다.

스레드의 중단 정책을 구현하는 코드 만이 중단 요청을 삼킬 수 있습니다. 범용 작업 및 라이브러리 코드는 중단 요청을 삼켜서는 안됩니다.


15
에서 문서 가 밝혔다있어 규칙에 따라, 어떤 방법이 던지는 종료하는 것이 " InterruptedException 투명 도료 상태를 중단 이 그렇게 할 때. 나는이 관점에서 답변을 명확하게 생각 하는 이유 는 인터럽트 상태를 유지해야합니다.
스텔리오스 Adamantidis

또한 다른 "배달 메커니즘"을 통해이 상태에 대한 알림을받은 후에 interrupt()는 호출이 중단 된 플래그 를 설정 하는 유일한 방법 이라는 점에 주목할 필요가 InterruptedException있습니다.
sevo

67

이 코드 샘플은 약간 명확하다고 생각합니다. 작업을 수행하는 클래스 :

   public class InterruptedSleepingThread extends Thread {

        @Override
        public void run() {
            doAPseudoHeavyWeightJob();
        }

        private void doAPseudoHeavyWeightJob() {
            for (int i=0;i<Integer.MAX_VALUE;i++) {
                //You are kidding me
                System.out.println(i + " " + i*2);
                //Let me sleep <evil grin>
                if(Thread.currentThread().isInterrupted()) {
                    System.out.println("Thread interrupted\n Exiting...");
                    break;
                }else {
                    sleepBabySleep();
                }
            }
        }

        /**
         *
         */
        protected void sleepBabySleep() {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                //e.printStackTrace();
                Thread.currentThread().interrupt();
            }
        }
    }

메인 클래스 :

   public class InterruptedSleepingThreadMain {

        /**
         * @param args
         * @throws InterruptedException
         */
        public static void main(String[] args) throws InterruptedException {
            InterruptedSleepingThread thread = new InterruptedSleepingThread();
            thread.start();
            //Giving 10 seconds to finish the job.
            Thread.sleep(10000);
            //Let me interrupt
            thread.interrupt();
        }

    }

상태를 다시 설정하지 않고 인터럽트 호출을 시도하십시오.


13
결론은 ??
Scott 混合 理论

3
감사. : 나는 당신이 지금 무슨 뜻인지 볼 repl.it/@djangofan/InterruptedThreadExample
djangofan

20

노트 :

http://download.oracle.com/javase/7/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html

오랜 시간 동안 대기하는 스레드를 어떻게 중지합니까 (예 : 입력)?

이 기술이 작동하려면 인터럽트 예외를 포착하고 처리 할 준비가되지 않은 메소드가 즉시 예외를 재확인하는 것이 중요합니다. 우리는 예외를 다시 던지는 것이 항상 가능한 것은 아니기 때문에 다시 던지기보다는 재 검증을 말합니다. InterruptedException을 잡는 메소드가이 (확인 된) 예외를 발생 시키도록 선언되지 않은 경우, 다음과 같은 incantation으로 "자체를 다시 인터럽트"해야합니다.

Thread.currentThread().interrupt();

이를 통해 스레드는 가능한 한 빨리 InterruptedException을 다시 발생시킵니다.


2

나는 그것이 나쁜 습관이거나 적어도 약간 위험하다고 생각합니다. 일반적으로 높은 수준의 방법은 차단 작업을 수행하지 않으며 InterruptedException거기서 보지 않습니다 . 인터럽트 가능한 작업을 수행하는 모든 장소에서 마스크를 숨기면 절대 얻을 수 없습니다.

Thread.currentThread.interrupt()다른 예외 또는 시그널링 인터럽트 요청을 다른 방식으로 제기하지 않는 유일한 이론적 근거 (예 : interrupted스레드의 메인 루프에서 로컬 변수 변수 설정 )는 finally블록 과 같이 예외로 실제로 아무것도 할 수없는 상황 입니다.

Thread.currentThread.interrupt()전화의 의미를 더 잘 이해하려면 Péter Török의 답변을 참조하십시오 .


0

자바 문서에서 참조

이 스레드가 wait (), join (), sleep (long) 호출에서 차단되면 인터럽트 상태가 지워지고 InterruptedException이 수신됩니다.

이 스레드가 I / O 작업에서 차단되면 스레드의 인터럽트 상태가 설정되고 스레드는 ClosedByInterruptException을 수신합니다.

이 스레드가 선택기에서 차단되면 스레드의 인터럽트 상태가 설정되고 선택 작업에서 즉시 반환됩니다.

이전 조건 중 어느 것도 유지되지 않으면이 스레드의 인터럽트 상태가 설정됩니다.

따라서 @Ajay George Answer의 sleepBabySleep () 메소드를 I / O 작업 또는 sysout으로 변경하면 프로그램을 중지하기 위해 상태를 다시 설정할 필요가 없습니다. (BTW, 그들은 심지어 InterruptedException을 던지지 않습니다)

@ Péter Török이 말한 것처럼 => 상태를 유지하기 위해 수행됩니다. (특히 InterruptedException을 발생시키는 메소드)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.