「こんにちは、アミーゴ! エリーのキャンセルのアイデアは素晴らしかったと認めざるを得ません。」

「はい。」

「実際、同様のものがThreadクラスに存在します。変数だけがisCancelと呼ばれていません。 isInterruptと呼ばれます。そして、スレッドを停止するために使用されるメソッドはcancel()ではなく、 interrupt()です。」

"本当?"

「はい。見てください。」

コード 説明
class Clock implements Runnable
{
public void run()
{
Thread current = Thread.currentThread();

while (!current.isInterrupted())
{
Thread.sleep(1000);
System.out.println("Tick");
}
}
}
複数のスレッドが同じClock オブジェクトの run メソッドを呼び出すことができるため、現在のスレッドの Thread オブジェクトを取得します

Clock クラスは、現在のスレッドのisInterrupt変数が falseである限り、「Tick」という単語を 1 秒に 1 回コンソールに書き込みます。

isInterrupt がtrueになると、run メソッドは終了します。

public static void main(String[] args)
{
Clock clock = new Clock();
Thread clockThread = new Thread(clock);
clockThread.start();

Thread.sleep(10000);
clockThread.interrupt();
}
メインスレッドは、永久に実行されるべき子スレッド (クロック) を開始します。

10 秒待ってから、 割り込みメソッドを呼び出してタスクをキャンセルします。

メインスレッドは作業を完了します。

クロック スレッドは作業を終了します。

さらに、runメソッドの無限ループで好んで使用されるsleepメソッドは、 isInterrupt変数を自動的にチェックします。スレッドがsleepメソッドを呼び出す場合、メソッドはまずそのスレッドに対してisInterrupt がtrue であるかどうかを確認します。true の場合、メソッドはスリープしません。代わりに、InterruptedException例外がスローされます。

「なぜ例外をスローするのでしょうか? isCancel() の代わりに単純に isInterrupted() をループ内に置いたほうが良いのではないでしょうか?」

"まずrunメソッドには常にループがあるとは限りません。このメソッドは、他のメソッドへの数十回の呼び出しで構成されているだけかもしれません。その場合、各メソッド呼び出しの前に isInterrupted チェックを追加する必要があります。"

第 2 に、多くのさまざまなアクションを伴う一部のメソッドは、実行に非常に長い時間がかかる可能性があります。」

"第三に、例外のスローは isInterrupted チェックを置き換えるものではありません。これは単なる便利な追加です。スローされた例外により、コール スタックをすぐに runメソッド自体に巻き戻すことができます。"

"第 4 に、sleep メソッドは頻繁に使用されます。結局のところ、この便利なメソッドは、暗黙のチェックによって強化されていますが、同様に役に立ちます。まるで誰も特別にチェックを追加していないかのように見えますが、チェックは実際に存在します。これは、次のような場合に非常に価値があります。他人のコードを使用しているため、自分でチェックを追加することはできません。」

"第 5 に、追加のチェックによってパフォーマンスが低下することはありません。sleep メソッドを呼び出すということは、スレッドが (スリープ以外) 何もしてはいけないことを意味するため、余分な作業が誰にも迷惑になることはありません。"

「それらは深刻な議論です。」

"そして最後に、これは次のとおりです。 run メソッドは、他の人のコード、つまりアクセス権 (ソース コードやコードを変更する権利) を持たないコードを呼び出すことができます。isInterrupted チェックがない可能性があり、すべての例外をキャッチするには、 「try ... catch (Exception e)」を実行してください。

スレッドが停止されることは誰も保証できません。スレッド自体を停止できるのはスレッドだけです。