従来の方法はスレッドを中断することですが、これには当然、スレッドが中断を適切に処理する必要があります。
これは、ブロッキング メソッドの周りで s を適切にキャッチして処理し、それ以外の場合は定期的にフラグInterruptedException
をチェック (およびそれに基づいて動作) することを意味します。interrupted
API や言語仕様には、割り込みを特定のキャンセル セマンティクスに関連付けるものはありませんが、実際には、キャンセル以外の目的で割り込みを使用することは脆弱であり、大規模なアプリケーションで維持することは困難です。[...]
中断は通常、キャンセルを実装する最も賢明な方法です。
セクション 7.1.1 のJava Concurrency in Practiceと述べています。同じものからの割り込みを適切に処理する例 (これはプロデューサー スレッドであり、コンシューマーではありませんが、現在のコンテキストではその違いは無視できます):
class PrimeProducer extends Thread {
private final BlockingQueue<BigInteger> queue;
PrimeProducer(BlockingQueue<BigInteger> queue) {
this.queue = queue;
}
public void run() {
try {
BigInteger p = BigInteger.ONE;
while (!Thread.currentThread().isInterrupted())
queue.put(p = p.nextProbablePrime());
} catch (InterruptedException consumed) {
/* Allow thread to exit */
}
}
public void cancel() { interrupt(); }
}
別の解決策は、タイムアウト パラメータをpoll
適度に低く設定することです。これにより、スレッドが定期的にウェイクアップし、割り込みに十分迅速に気付くことができます。それでも、特定のスレッド キャンセル ポリシーに従って、InterruptedException を明示的に処理することは常に良い方法だと思います。