[java] 내가 아닌 경우 누가 Java Thread interrupt () 메서드를 호출합니까?

저는 실제로 Java Concurrency를 읽고 다시 읽었으며, 주제에 대한 여러 스레드를 읽었으며 IBM 기사 Dealing with InterruptedException을 읽었습니다. 실제로 지만 깨질 수 있다고 생각하는 부분을 파악하지 못했습니다. 두 가지 질문으로 요약됩니다.

  1. 내가 다른 스레드를 중단하지 않는 경우 InterruptedException을 트리거 할 수있는 것은 무엇입니까? 입니까?

  2. interrupt ()를 사용하여 다른 스레드를 중단하지 않는 경우 (예를 들어 독약 및 while (! cancelled) 스타일 루프 (둘 다 JCIP에서 설명 ) 와 같은 작업 스레드를 취소하는 다른 방법을 사용하고 있기 때문에 ) 않는 예외 : InterruptedException은 다음을 의미? 잡으면 어떻게해야하나요? 내 앱을 종료 하시겠습니까?



답변

스레드 인터럽트 메커니즘은 (협력하는) 스레드가 수행중인 작업을 중지하라는 요청에 응답하는 데 선호되는 방법입니다. 모든 스레드 (내 생각에 스레드 자체 포함)는 스레드를 호출 할 수 interrupt()있습니다.

실제로,에 대한 일반적인 사용 사례 interrupt()에는 일종의 프레임 워크 또는 관리자가 작업자 스레드가 수행중인 작업을 중지하도록 지시하는 것이 포함됩니다. 작업자 스레드가 “인터럽트 인식”인 경우 예외를 통해 중단되었거나 중단 된 플래그를 주기적으로 확인하여 중단되었음을 알 수 있습니다. 중단되었음을 알아 차리면 잘 작동하는 스레드가 수행중인 작업을 포기하고 스스로 종료됩니다.

위의 사용 사례를 가정 할 때 코드가 Java 프레임 워크 내에서 실행되거나 일부 작업자 스레드에서 실행되는 경우 코드가 중단 될 수 있습니다. 그리고 그것이 중단 될 때, 당신의 코드는 자신이하는 일을 포기하고 가장 적절한 수단에 의해 스스로 종료되도록해야합니다. 코드가 호출 된 방법에 따라 반환하거나 적절한 예외를 throw하여 수행 할 수 있습니다. 그러나 그것은 아마 호출해서는 안됩니다System.exit() . (응용 프로그램이 중단 된 이유를 반드시 알 수는 없으며 프레임 워크에 의해 중단되어야하는 다른 스레드가 있는지 확실히 알 수 없습니다.)

반면에 코드가 일부 프레임 워크의 제어하에 실행되도록 설계되지 InterruptedException않은 경우 예상치 못한 예외 라고 주장 할 수 있습니다 . 즉 버그입니다. 이 경우 다른 버그와 마찬가지로 예외를 처리해야합니다. 예를 들어 확인되지 않은 예외로 래핑하고 다른 예기치 않은 확인되지 않은 예외를 처리하는 동일한 지점에서 포착하고 기록합니다. (또는 응용 프로그램은 단순히 인터럽트를 무시하고 수행중인 작업을 계속할 수 있습니다.)


1) 다른 스레드를 직접 중단하지 않는 경우 InterruptedException을 트리거 할 수있는 것은 무엇입니까?

귀하의 경우 하나의 예는 Runnable객체가를 사용하여 실행 ExecutorServiceshutdownNow()서비스 호출됩니다. 그리고 이론적으로는 타사 스레드 풀 또는 스레드 관리 프레임 워크가 합법적으로 이와 같은 작업을 수행 할 수 있습니다.

2) interrupt () 사용하여 다른 스레드를 중단하지 않는 경우 … InterruptedException then은 무엇을 의미합니까? 잡으면 어떻게해야하나요? 내 앱을 종료 하시겠습니까?

코드베이스를 분석하여 무엇이 interrupt() 호출하는 이유와 이유 . 이를 파악한 후에는 >> << 앱의 일부에서 수행해야하는 작업을 해결할 수 있습니다.

InterruptedException던지는 지 알 때까지 나는 그것을 하드 오류로 취급하는 것이 좋습니다 . 예를 들어 스택 트레이스를 로그 파일에 인쇄하고 앱을 종료합니다. (분명히 이것이 항상 정답은 아닙니다.하지만 요점은 이것이 “버그”이며 개발자 / 관리자의주의를 끌 필요가 있다는 것입니다.)

3) 누구 / 무슨 전화인지 어떻게 알 수 interrupt()있습니까?

이것에 대한 좋은 대답은 없습니다. 내가 제안 할 수있는 최선의 방법은에 중단 점을 설정 Thread.interrupt()하고 호출 스택을 보는 것입니다.


답변

코드를 다른 라이브러리와 통합하기로 결정하면 코드를 호출 할 수 있습니다 interrupt(). 예를 들어 앞으로 ExecutorService 내에서 코드를 실행하기로 결정하면 다음을 통해 강제 종료 될 수 있습니다.interrupt() .

간단히 말해서 코드가 현재 실행중인 위치 뿐만 아니라 향후 어떤 컨텍스트에서 실행 될지 고려할 것입니다. 예를 들어 라이브러리에 넣을 건가요? 컨테이너 ? 다른 사람들은 그것을 어떻게 사용합니까? 재사용 하시겠습니까?


답변

다른 사람들이 지적했듯이 스레드 중단 (실제로는 차단 호출 중단)은 일반적으로 깔끔하게 종료하거나 진행중인 활동을 취소하는 데 사용됩니다.

그러나 InterruptedException단독으로 “종료 명령”으로 취급해서는 안됩니다 . 대신 인터럽트를 스레드의 실행 상태를 제어하는 ​​수단으로 생각해야합니다 Object.notify(). 에 대한 호출에서 깨어 난 후 현재 상태를 확인하는 것과 같은 방식으로 Object.wait()(웨이크 업이 대기 조건이 충족되었음을 의미한다고 가정하지 않음), 인터럽트로 넛지 한 후 중단 된 이유 를 확인해야합니다. . 일반적으로이를 수행하는 방법이 있습니다. 예를 들어, java.util.concurrent.FutureTask갖는 isCancelled()방법.

코드 샘플 :

public void run() {
    ....
    try {
        .... // Calls that may block.
    } catch (InterruptedException e) {
        if (!running) {  // Add preferred synchronization here.
            return; // Explicit flag says we should stop running.
        }
        // We were interrupted, but the flag says we're still running.
        // It would be wrong to always exit here. The interrupt 'nudge'
        // could mean something completely different. For example, it
        // could be that the thread was blocking on a read from a particular
        // file, and now we should read from a different file.
        // Interrupt != quit (not necessarily).
    }
    ....
}
public void stop() {
    running = false; // Add preferred synchronization here.
    myThread.interrupt();
}


답변

질문의 문제는 “나”입니다. “I”는 일반적으로 클래스의 단일 인스턴스를 나타냅니다. 즉, 저수준 코드 (클래스)의 특정 부분이 전체 시스템의 구현에 의존해서는 안됩니다. “아키텍처”결정 (예 : 실행할 플랫폼)을 몇 가지 내렸다고 말했듯이.

JRE에서 발생할 수있는 예상치 못한 인터럽트는 java.util.concurrent애플릿 에서 취소 된 작업입니다 .

스레드 인터럽트 처리는 일반적으로 잘못 작성됩니다. 따라서 가능한 경우 인터럽트를 발생시키지 않도록 아키텍처 결정을 제안합니다. 그러나 코드 처리 인터럽트는 항상 올바르게 작성되어야합니다. 지금은 플랫폼에서 인터럽트를 가져올 수 없습니다.


답변

자신의 스레드 클래스 (확장 java.lang.Thread)를 만들고 interrupt()메서드를 재정 의하여이를 배울 수 있습니다 . 여기에서 스택 추적을 String 필드에 기록한 다음 super.interrupt ()로 전송할 수 있습니다.

public class MyThread extends Thread {

    public volatile String interruptStacktrace; // Temporary field for debugging purpose.

    @Override
    public void interrupt() {
        interruptStacktrace = dumpStack(); // You implement it somehow...

        super.interrupt();
    }
}


답변

이미 언급했듯이 다른 라이브러리가 스레드를 중단 할 수 있습니다. 라이브러리가 코드에서 스레드에 대한 명시 적 액세스 권한이 없더라도 다음 메서드를 사용하여 실행중인 스레드 목록을 가져 와서 인터럽트 할 수 있습니다 .


답변

나는 당신이 방해에 대해 약간 혼란스러워하는 이유를 이해한다고 생각합니다. 내 대답을 고려하십시오.

내가 다른 스레드를 중단하지 않는 경우 InterruptedException을 트리거 할 수있는 것은 무엇 입니까?

먼저 다른 스레드를 중단 할 수 있습니다. JCiP에서는 자신이 소유하지 않은 스레드를 절대 중단해서는 안된다는 것을 알고 있습니다. 그러나이 진술은 적절하게 이해되어야합니다. 의미하는 바는 임의의 스레드에서 실행될 수있는 코드가 스레드의 소유자가 아니기 때문에 인터럽트 정책에 대한 단서가 없기 때문에 인터럽트를 처리해서는 안된다는 것입니다. 따라서 다른 스레드에 대한 중단을 요청할 수 있지만 해당 소유자가 중단 작업을 수행하도록합니다. 작업 코드가 아니라 그 안에 캡슐화 된 중단 정책이 있습니다. 적어도 중단 플래그를 정중하게 설정하십시오!

여전히 중단이있을 수있는 이유는 여러 가지가 있습니다. 시간 초과, JVM 인터럽트 등일 수 있습니다.

interrupt ()를 사용하여 다른 스레드를 중단하지 않는 경우 (예를 들어 독약 및 while (! cancelled) 스타일 루프 (둘 다 JCIP에서 설명)와 같은 작업 스레드를 취소하는 다른 방법을 사용하고 있기 때문에) InterruptedException은 무엇을 의미합니까? 하나 잡으면 어떻게해야하나요? 내 앱을 종료 하시겠습니까?

여기서 매우 조심해야합니다. InterruptedException (IE)을 던진 스레드를 소유하고 있다면, 그것을 잡을 때해야 할 일을 알고 있습니다. 앱 / 서비스를 종료하거나이 죽은 스레드를 새 스레드로 교체 할 수 있습니다! 그러나 스레드를 소유하지 않은 경우 IE를 잡을 때 호출 스택 위로 다시 던지거나 무언가를 수행 한 후 (로깅 일 수 있음) 인터럽트 된 상태를 재설정하여이 스레드를 소유 한 코드가 제어에 도달 할 때 스레드가 중단되었음을 확인하고 중단 정책 만 알고 있기 때문에 원하는대로 조치를 취합니다.

이것이 도움이 되었기를 바랍니다.