最初にいくつかの説明:
スレッドの中断ステータスは基本的にブールフラグであり、によって「true」に設定されinterrupt()
ます。このフラグの現在の状態は、を使用して読み取るThread.currentThread().isInterrupted()
ことができます。
割り込み可能な操作(Object.wait()
またはThread.sleep()
)が割り込みフラグが設定されていることを検出すると、フラグをスローInterruptedException
し、同時にフラグをクリア(「false」に設定)します。これは次のようになります。
if ( Thread.interrupted() ) { throw new InterruptedException(); }
Thread.interrupted()
中断されたフラグを暗黙的にクリアすることに注意して覚えてください!これは、catch( InterruptedException ie) {...}
が実行されるまでに、スレッド自体がそれが中断されたことを認識しないことを意味します。
そうは言っても、2つの例を見てみましょう。
最初に、キャンセルをサポートするタスクの例。ここでは、タスクが中止される前にどこまで進行するかは実際には気にしません。
public void run() {
int x = 0;
try {
while (x < 10) {
Thread.sleep(1000); // Some interruptible operation
x++;
}
System.out.println("x = " + x);
} catch (InterruptedException ie) {
System.out.println("Interrupted: x = " + x);
// We know we've been interrupted.
// Let the caller know it, too:
Thread.currentThread().interrupt();
}
}
このコードは、xを0から10までカウントしようとします。中断されない場合は、完了して「x=10」を出力します。ただし、その間にスレッドが中断されると、InterruptedException
がスローされ、xをインクリメントする進行中のタスクが中止されます。この場合、出力は、スレッドがいつ中断されたかに応じて、「Interrupted:x = 0」から「Interrupted:x=9」までのいずれかになります。
終了する前にスレッドの中断フラグを復元することをお勧めします。そうしないと、このrun()
メソッドの呼び出し元に中断ステータスが表示されないためです。
ここで、タスクを完全に実行することが重要であり、出力が常に「x = 10」になるようにする場合、つまりタスクがキャンセルをサポートしない場合は、別のアプローチが必要です。
public void run() {
int x = 0;
boolean wasInterrupted = false; // <- This is the local variable to store the interruption status
while (x < 10) {
wasInterrupted = wasInterrupted || Thread.interrupted(); // not really needed in this case, but for the sake of completeness...
try {
Thread.sleep(1000); // <- Some interruptible operation
} catch (InterruptedException e) {
wasInterrupted = true;
}
x++;
}
System.out.println("x = " + x);
if ( wasInterrupted ) {
Thread.currentThread().interrupt();
}
}
InterruptedException
この場合、タスクが完了するまで、処理を続行します。wasInterrupted
良い状態を維持するために、中断を検出した場合は、メソッドから戻る前に中断フラグを正しく設定できるように、その条件をに格納します。
それが意味するものです
中断ステータスをローカルに保存し、戻る直前に復元する必要があります。
この方法で中断を処理する必要は厳密にはないため、「すべき」と表示されます。無視InterruptedException
してタスクを完了してから戻ることもできます。ただし、これは上記の良い方法ではなく、シナリオによっては問題が発生する可能性があります。