6

私は非常に混乱しており、InterruptedException を飲み込んではいけない理由を理解できません。

IBMの記事によると

ブロッキング メソッドが割り込みを検出して InterruptedException をスローすると、割り込み状態がクリアされます。InterruptedException をキャッチしても再スローできない場合は、割り込みが発生したという証拠を保持して、コール スタックの上位にあるコードが割り込みを認識し、必要に応じて応答できるようにする必要があります。

public class TaskRunner implements Runnable {
    private BlockingQueue<Task> queue;

    public TaskRunner(BlockingQueue<Task> queue) { 
        this.queue = queue; 
    }

    public void run() { 
        try {
             while (true) {
                 Task task = queue.take(10, TimeUnit.SECONDS);
                 task.execute();
             }
         }
         catch (InterruptedException e) { 
           Thread.currentThread().interrupt();//preserve the message
             return;//Stop doing whatever I am doing and terminate

         }
    }
}

また、Java Concurrency in Practice では、第 7.1.3 章: 割り込みへの対応でこれについて詳しく説明しています。そのルールは次のとおりです。

スレッドの割り込みポリシーを実装するコードのみが、割り込み要求を飲み込むことができます。汎用タスクおよびライブラリ コードは、割り込み要求を飲み込むべきではありません。

1.より高いコールスタックのコードで Thread.currentThread().interrupt(); によって設定されたステータスを利用する方法を誰でも説明できますか? スレッドが終了したときの catch ブロックで?

また、上記のルールについて説明してください。

4

1 に答える 1

6

スレッド/スレッドプールのコンテキストで実行されると仮定したこの例を見てください。

public void run() {
  // Honor interrupts so that you can stop/kill the task
  while (!Thread.currentThread().interrupted()) {
    this.doSomeChunkOfWork();
  }    
}

上記のコードは、割り込み可能でデータをチャンクで処理するタスクを作成する方法の良い例です (あるソースから読み取り、データを部分的に処理することを考えてください)。ここで、doSomeChunkOfWorkが中断され、例外をキャッチしたとします。フラグを再度設定するか、フラグの割り込みステータスを維持しない限り、runメソッドは、メソッド呼び出しが返されたときに呼び出しスタックの奥深くで処理が中断されたことを認識できず、適切なロジックが台無しになります。

これが、スレッドが実際に中断されたかどうかを呼び出しスタックの下のメソッドが認識できるように、常にステータスを元に戻す理由です。これについて考えたい類推は、「じゅうたんの下の汚れを一掃しないでください」です。:)

于 2013-09-08T09:47:32.687 に答える