13

フューチャーをキャンセルせずに中断する方法はありますか?

java doc API:

boolean cancel(boolean mayInterruptIfRunning)

このタスクの実行をキャンセルしようとします。タスクがすでに完了している場合、すでにキャンセルされている場合、またはその他の理由でキャンセルできなかった場合、この試行は失敗します。成功し、cancelが呼び出されたときにこのタスクが開始されていない場合、このタスクは実行されません。タスクがすでに開始されている場合、mayInterruptIfRunningパラメーターは、タスクを停止するためにこのタスクを実行しているスレッドを中断する必要があるかどうかを決定します。

割り込みをキャプチャするには、割り込み例外を適切にキャッチするか、Runnable / Callableメソッド内のisInterrupted()メソッドを確認する必要があります。

しかし、Futureインターフェースを使用して実行中のFutureを中断する方法はありません

すべてのスレッドがエグゼキュータサービスプールにあるため、誰もthread.interrupt()を実行できません。フューチャーがキャンセルされたとき、またはスレッドプールが終了したときにのみ割り込みが発生すると想定されているのはそのためですか?

Futureインターフェースに割り込みメソッドがない理由を理解しようとしています。どんな助けでも大歓迎です

4

3 に答える 3

9

その理由は、Futureである抽象化と、スレッドでの具体的な実行の違いによるものです。未来が単一のスレッドに結び付けられているのか、複数のスレッドに結び付けられているのかはわかりません。先物は、新しいスレッドを開始したり、新しい先物を開始したりする可能性があります。

これらの抽象化は、クライアントコードと先物のエグゼキュータ間の相互作用と見なしてください。概念的には、キャンセルするのはあなたのタスクだったので、「私があなたに依頼したこのタスクをキャンセルする」と言うのは理にかなっています。忙しいのか、まだ始めていないのか、終わっているのか、大丈夫ですので、よろしければキャンセルさせていただきます。そのため、キャンセルメソッドがあります。

一方、「タスクを中断する」と言ってもあまり意味がありません。アクションの結果(Future)と実行モデル(Executorなど)の間の分離のため、クライアントはタスクを実行するために実行されているアクションについての知識を持っていません。次に、クライアントは、割り込みが適切であるか、必要であるか、またはサポートされているかを知ることをどのように期待できますか。

于 2012-01-22T00:18:55.253 に答える
0

いずれにせよ、タイムアウトを使用できるので、待機を中断します。

get(long timeout, TimeUnit unit) 
于 2012-02-01T20:06:26.843 に答える
0

これを行うための便利なユースケースがあります。

Future APIの問題は、実行が停止したことを検出する機能を提供しないことです。isCancelled()isDone()はどちらも、Callableの実行が継続されていても、trueを返します。

したがって、この段階でのFutureAPIの抽象化のレベルについては実際には関係ありません。ただし、タスクの終了を識別することはできません。言い換えると、キャンセルリクエストと完了したキャンセルアクションを区別することはできません。

回避策の1つは、質問「キャンセルされた未来が実際に終了するのを待つ」で行われたように、 CountdownLatchを使用することです。これにより、待機中の呼び出し元に、タスクが実際に実行されたことを通知します。停止するように通知するだけではありません。

于 2016-01-30T00:20:58.907 に答える