スレッドがキャンセルされたとき
myWorkerThread.cancel(true/false);
doneメソッドは(非常に驚くべきことに)cancelメソッド自体によって呼び出されます。
予想されることですが、実際には実行されません:
-cancelを呼び出します(mayInterruptを使用するかどうかに関係なく)-cancel
スレッドのキャンセルを設定します
-doInBackgroundが終了します-done
が呼び出されます*
(*doneはEDTにエンキューされますつまり、EDTがビジーの場合、EDTが実行を終了した後に発生します)
実際に何が起こるか:
-キャンセルを呼び出す(mayInterruptを使用するかどうかに関係なく)
-キャンセルスレッドキャンセルの設定
-完了はキャンセルコードの一部として呼び出されます*
-doInBackgroundは、ループが終了すると終了します
(*完了はEDTにエンキューされませんが、キャンセルコールに呼び出されるため、EDTに非常にすぐに影響します。これは、多くの場合GUIです)
これを証明する簡単な例を示します。
コピー、貼り付け、実行します。
1.done内でランタイム例外を生成します。スタックスレッドは、doneがcancelによって呼び出されることを示しています。
2.キャンセルから約4秒後に、doInBackgroundから挨拶が届きます。これは、スレッドが終了する前にdoneが呼び出されたことを激しく証明します。
import java.awt.EventQueue;
import javax.swing.SwingWorker;
public class SwingWorker05 {
public static void main(String [] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
W w = new W();
w.execute();
Thread.sleep(1000);
try{w.cancel(false);}catch (RuntimeException rte) {
rte.printStackTrace();
}
Thread.sleep(6000);
} catch (InterruptedException ignored_in_testing) {}
}
});
}
public static class W extends SwingWorker <Void, Void> {
@Override
protected Void doInBackground() throws Exception {
while (!isCancelled()) {
Thread.sleep(5000);
}
System.out.println("I'm still alive");
return null;
}
@Override
protected void done() {throw new RuntimeException("I want to produce a stack trace!");}
}
}