免責事項:この回答にはチュートリアルのキャラクターが含まれています。
基本的なアプローチThread.sleep
:最初は物事をシンプルに保ち、メソッド中の中断には対処しません。基本的に、runメソッドがループのすべての反復でチェックする外部設定可能な変数が必要です。次に、その変数を設定して、run()
メソッドを正常に終了できます。このイディオムがJava以外の言語で簡単に使用できることに注意してください。
例えば:
public class MyThreadedClass extends Thread {
private volatile boolean completed = false;
public void setCompleted() {
this.completed = true;
}
public void run()
{
while (!completed) {
// do anything you fashion
}
}
public static void main(String... args)
{
MyThreadedClass x = new MyThreadedClass();
MyThreadedClass y = new MyThreadedClass();
x.start();
y.start();
x.setCompleted(); // will complete as soon as the latest iteration finishes
...
}
}
コメント:volatileフラグはcompleted
、関数の制御外で変更される可能性がある(および変更される)ことをコンパイラーに通知しrun()
ます。つまり、別のスレッドが変更する可能性があります。そうしないと、クラスの唯一の同期動作に従って、ループ内の反復チェックが誤って最適化される可能性があります。
あなたの特定run()
のケースでは、for
ループを利用するので、私たちのアプローチは次のように変換されます。
public void run()
{
try {
for(int i=0;i<20 && !completed;++i) {
Thread.sleep(500);
System.out.print(i +"\n"+ "..");
}
} catch(Exception e) {
e.printStackTrace();
}
}
コメント:それはかなり明白なので、スリープコールのために最大500ミリまで待たなければならない場合があります。ただし、一般に、コードで変数の状態を変更する操作を実行する必要がある場合(特に、そのような変数が複数のスレッド間で共有されている場合)、このようにして、これらの変数を誤った状態のままにしないでください。実際には、終了を制御するため、トランザクションを適切に処理できます。これは明らかに、ループの各反復の終わりに、変数の状態が一貫していることを前提としています。
ここで、の中断を処理するための基本的なアプローチを改善しましょうThread.sleep
。
完全な回答:この回答には、呼び出し側からのThread.interrupt()
メソッドの使用が含まれます。これにより、アプローチはJavaに厳密に固有になります。
public class MyThreadedClass extends Thread {
public void run()
{
try {
for(int i=0;i<20 && !this.isInterrupted();++i) {
Thread.sleep(500);
System.out.print(i +"\n"+ "..");
...
// some molassy slow code here, where you may sprinkle isInterrupted()
// checks and consequent break statements
}
} catch(InterruptedException e) {
// do whatever you need to clean things up
} catch(Exception e) {
// handle other exceptions as seen fit
}
}
public static void main(String... args)
{
MyThreadedClass x = new MyThreadedClass();
x.start();
// will complete
// a) as soon as one isInterrupted() check breaks the loop, or
// b) "immediately" during the blocking call to sleep()
x.interrupt();
...
}
}
コメント:この場合、あなたはすでにあなたの仕事の半分をスレッド自体によって行っています。通話中に中断するだけでよい場合は、必要に応じて、状態をクリーンアップするためThread.sleep
の処理以外のことを行う必要はありません。InterruptedException
代わりに、「スロー」コード中に割り込みをかける必要がある場合は、this.isInterrupted()
好きな場所(おそらく複数の場所)で呼び出して、ループを中断する必要があります。ループ条件内の呼び出しは一般的ですが、必須ではありません。
詳細については、Java同時実行割り込みのチュートリアルを参照してください。