2017-05-06 1 views
1

아래 코드를 작성하면 스레드를 인터럽트하거나 종료 할 수 없습니다. 또한 InterruptedException을 throw하지 않습니다.sleep() 및 wait() 같은 메서드를 차단할 때만 InterruptedException이 throw되는 이유는 무엇입니까?

Thread loop = new Thread(
    new Runnable() { 
    @Override 
    public void run() { 
     while (true) { 
     } 
    } 
    } 
); 
loop.start(); 
loop.interrupt(); 

이 스레드를 중단하려면, 나는 다음과 같이 내 코드를 수정해야합니다

Thread loop = new Thread(
    new Runnable() { 
    @Override 
    public void run() { 
     while (true) { 
     if (Thread.interrupted()) { 
      break; 
     } 
     // Continue to do nothing 
     } 
    } 
    } 
); 
loop.start(); 
loop.interrupt(); 

내 질문은,

  1. 자바는 이러한 방식으로 설계 예외 : InterruptedException 그 이유

    sleep() 및 wait()와 같은 메서드를 차단할 경우에만 throw됩니다.

  2. 정상적인 코드에서 위의 코드 스 니펫과 같이 수동으로 처리해야하는 이유는 무엇입니까? 인터럽트 플래그를 true로 설정할 때마다 Java가 InterruptedException을 throw하지 않는 이유는 무엇입니까? interrupt() 메서드를 통해?

InterruptedException에 대한 많은 블로그와 기사를 읽었지만 설득력있는 대답을 찾지 못했습니다. 자바의 http://codepumpkin.com/interruptedexception-java-multithreading/

+6

정상적인 실행 중에 코드가 인터럽트 될 수있는 경우 모든 코드 줄을 검사해야하며 속도가 매우 느립니다. 또한 일부 코드는 실행이 완료되어야합니다. 그렇지 않으면 예기치 않은 버그가 발생합니다 (예 : 리소스를 닫지 않는 등). – 4castle

+1

그것은 기본적으로 deprecated stop() 메소드가 수행 한 것입니다. javadoc에서 더 이상 사용되지 않는 이유를 읽을 수 있습니다. 그러나 4 캐슬은 그것을 아주 잘 설명했다. –

+1

자바 중단은 * 협력 적 *입니다. 하나의 스레드는 다른 스레드에게 수행중인 작업을 중단하도록 요청할 수 있지만 다른 스레드가 즉시 또는 심지어 계속해서이를 수행 할 필요는 없습니다. –

답변

3

자바는 예외 : InterruptedException가 수면과 같은 방법을 차단하는 경우에만 발생되고 있음을 같은 방식으로 설계되는 이유 1)() 및 대기().

thread.interrupt()의 전체적인 점은 협조적이다. 스레드가 인터럽트되었지만 인터럽트 플래그가 Thread.currentThread().isInterrupted()을 사용하여 검사해야하므로 필요에 따라 공유 터미네이션을 올바르게 관리하고 공유 객체, 잠금, 최종 블록 등을 정리할 수 있습니다.

tutorial on the subject에서 인용 할 때는 강조합니다.

인터럽트는 스레드가 수행중인 작업을 중지하고 다른 작업을해야한다는 것을 나타냅니다. 프로그래머가 스레드가 인터럽트에 대해에 응답하는 방법을 정확하게 결정할 때까지는 이지만 스레드가 종료되는 것은 매우 일반적입니다. 던져 InterruptedException

방법은 잠금 장치 및 기타 조건에 대기중인 것들입니다.이것들은 인터럽트가 다시 발생했기 때문에 스레드가 종료되기 전에 다시 스스로를 지울 수 있다고 말한다.

2) 정상 코드에서 위의 코드 스 니펫과 같이 수동으로 처리해야하는 이유는 무엇입니까? interrupt() 메소드를 통해 인터럽트 플래그를 true로 설정할 때마다 Java가 InterruptedException을 던지지 않는 이유는 무엇입니까?

대안

InterruptedException에 관계없이 프로그램을 기대되었는지 여부를 언제든지 발생 된 수있는 RuntimeException 될 가지고 있었을 것이다. stop() 및 더 이상 사용되지 않는 Thread 메서드의 일부는 다양한 언어 구문을 위반하는 경향이있어 응용 프로그램 메모리가 잘못된 상태로 남을 수 있습니다. 여기에 more details about that이 있습니다.

InterruptedException (RuntimeException)이라면 마찬가지입니다. 쓰레드가 공유 객체를 변경하고 중류 인 경우에만 예기치 않은 RuntimeException이 던져 지거나 완전히 중단되었다고 상상할 수 있습니다. 업데이트되는 공유 객체는 쉽게 잘못된 상태로 남을 수 있습니다.

if (Thread.interrupted()) { 

이 그것이 나쁜 패턴 스레드에 인터럽트 플래그를 지 웁니다 때문에 전화를 할 수있는 권리 방법은 아닙니다

. 다음을 사용하십시오 :

if (Thread.currentThread().isInterrupted()) { 

이 가능한 경우 수행해야 인터럽트 플래그를 유지합니다. 또한 InterruptedException이 발생하면 인터럽트 플래그도 지 웁니다. 그것이 좋은 패턴입니다 :

try { 
    ... 
} catch (InterruptedException ie) { 
    // re-interrupt the thread to propagate the interrupt flag 
    Thread.currentThread().interrupt(); 
    // handle the interrupt here by probably quitting the thread 
} 

라이브러리가 인터럽트 플래그를 "삼키는"많은 문제가 있습니다. 코드가 작더라도 더 큰 블록으로 복사 될 수 있으므로 항상 인터럽트 플래그를 좋은 패턴으로 복원 할 수 있습니다.

+1

고마워 그레이 .. 이해 .. !! –

+1

Re : "또한 인터럽트 플래그를 지우는 InterruptedException도 잡았을 때": 그건 옳지 않습니다. 오히려, * InterruptedException을 throw하는 JDK 메서드는 모두 인터럽트 플래그를 지우는 것입니다. 그러나 플래그가 설정된 경우, 어떤 이유로 든 InterruptedException을 catch하면 그 예외를 잡는 단순한 동작으로 플래그가 지워지지 않습니다. 예 : http://ideone.com/H4wzrA. 그럼에도 불구하고 제안 된 패턴은 맞습니다. – ruakh

+0

좋은 교정 @ruakh. – Gray

1

초기 버전은 스레드를 죽일 수 있기를 사용하지만, 여러 운영 체제를 지원하기 위해 노력하고 때 신속하게 문제가되었다 :

편집

는 예외 : InterruptedException에 좋은 기사를 발견했다. 매우 다른 방법이 있습니다. 운영 체제는 매우 다른 기능으로 스레딩을 구현합니다. 스레드가 중간 비행을 중단하면 안전하지 않은 것으로 간주되어 교착 상태와 같이 응용 프로그램의 다른 부분에서 예기치 않은 동작이 발생할 수 있습니다. 여기

자세한 내용 : https://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html

+2

stop() 메소드의 비추천에 불빛을 던지고 스레드를 죽이는 것에 대해 감사드립니다. 하지만 스레드를 중지하는 것이 아니라 소유자 스레드에서 자식 스레드를 방해하는 것입니다.우리는 예상치 못한 행동을 처리하기위한 예방 조치를 항상 취할 수 있습니다. 위의 4castle의 의견은 "정상적인 실행 중에 코드가 중단 될 수 있다면 모든 코드 줄을 검사해야하며 속도가 매우 느릴 것입니다." 어쨌든 감사드립니다. 답변을 upvoting :) –

+0

* "우리는 항상 예기치 않은 행동을 처리하는 예방 조치를 취할 수 있습니다."* 오, 정말? 말해주십시오. 스레드가 언제 종료 될지 정확히 알 수없는 경우 어떻게 실패 원 자성을 유지합니까? – scottb

+1

스레드가 현재 실행중인 컴파일 된 코드가 있습니다. OS가 다른 스레드에 CPU 시간 조각을 제공하기로 결정하지 않는 한, 언제든지 코드가 중단 될 수있는 방법이 없습니다. OS를 사용하는 대신에 뒤에서이 작업을 수행하는 대신 개발자가 편리한 시간에 스레드가 중단되도록하는 것이 중요합니다. Java 코드는 스레딩과 관련하여 다양한 기능을 제공하는 다양한 아키텍처에서 실행할 수 있으므로 절충안입니다. –

관련 문제