私は現在、FutureTasksとExecutorsを使用して、マルチスレッド環境で厄介なバグを探しています。基本的な考え方は、固定数のスレッドに、テーブルに表示される結果を計算する個々のFutureTasksを実行させることです(ここではGUIの側面を気にしないでください)。
私はこれを長い間見てきました、私は自分の正気を疑うようになり始めています。
このコードを考えてみましょう。
public class MyTask extends FutureTask<Result> {
private String cellId;
...
protected void done() {
if (isCancelled()) return;
try {
Result r = get(); // should not wait, because we are done
... // some processing with r
sendMessage(cellId, r);
} catch (ExecutionException e) { // thrown from get
...
} catch (InterruptedException e) { // thrown from get
...
}
}
...
}
MyTaskdone()
のインスタンスを処理するエグゼキュータによって呼び出された場合、タスクがキャンセルされたため、そこに到達したかどうかを確認します。もしそうなら、私は残りのすべての活動をスキップします、特に私は電話しませんsendMessage()
。
FutureTask.done()のドキュメントには次のように書かれています。
このタスクが状態isDoneに遷移するときに呼び出される保護されたメソッド(通常またはキャンセルを介して)。デフォルトの実装は何もしません。サブクラスは、このメソッドをオーバーライドして、完了コールバックを呼び出したり、簿記を実行したりできます。このメソッドの実装内でステータスを照会して、このタスクがキャンセルされたかどうかを判断できることに注意してください。(APIリファレンス)
しかし、のドキュメントから得られないのは、実行中FutureTask
のセマンティクスです。最初にチェックに合格したが、その直後に他のスレッドが私のメソッドを呼び出した場合はどうなりますか?それは私の仕事の考えを変え、それ以降に返信する原因になりますか? done()
isCancelled()
cancel()
isCancelled() == true
もしそうなら、メッセージが送信されたかどうかを後でどうやって知ることができますか?見てみるisDone()
と、タスクの実行が終了したisCancelled()
ことがわかりますが、そのときもそうであったように、メッセージを時間内に送信できるかどうかはわかりませんでした。
たぶんこれは明らかですが、私は今それを実際には見ていません。