私はExecutorServiceを使用して、何千もの小さな独立したタスクを処理しています。各タスクは、完了すると、結果を保存します(これは、trueまたはfalseのいずれかです)。
したがって、すべてのタスクを処理する代わりに、タスクが答えを見つけた場合は、スレッドプールを途中でシャットダウンしたいと思います。ここで非常に明白な何かが欠けているように感じます...
私はExecutorServiceを使用して、何千もの小さな独立したタスクを処理しています。各タスクは、完了すると、結果を保存します(これは、trueまたはfalseのいずれかです)。
したがって、すべてのタスクを処理する代わりに、タスクが答えを見つけた場合は、スレッドプールを途中でシャットダウンしたいと思います。ここで非常に明白な何かが欠けているように感じます...
この方法の使用を検討してくださいinvokeAny
。1つだけ完了すると戻ります。
あなたが表現した欲求は、「内側」と「外側」の区別がほとんどないクラインの壺を思い出させます。ここで、提出されたタスクは、スレッドプールの外側のラッチゲートに通知し、最初に実際のタスクの結果が表示されなかった状態から少なくとも1つの結果が表示された状態に移行するときにシャットダウンするExecutorService
必要があることを知る必要があります。
コードは書きませんが、解決策をスケッチします。タスクが完了したときに呼び出す必要のあるインターフェイスを定義すると役立つ場合があります。
interface TaskObserver
{
void completed(boolean result);
}
各タスクインスタンスは、そのようなを参照して構築できます。このインスタンスTaskObserver
では、タスク本体が完了する直前に呼び出し、呼び出し元に制御を戻しExecutorService
ます。このプロトコルへの参加を支援する基本クラスを作成することもできます。
public abstract class ObservableTask implements Callable<Boolean>
{
protected ObservableTask(TaskObserver observer)
{
if (null == observer)
throw NullPointerException();
observer_ = observer;
}
public final Boolean call()
{
final boolean result = evaluate();
observer_.completed(result);
return result;
}
protected abstract boolean evaluate();
private final TaskObserver observer_;
}
または、拡張機能を使用してタスクを定義する代わりに、コンストラクターで参照に加えてaへの参照を受け入れ、代わりに委任を通じて機能する、このような具象クラスを作成することもできます。Callable<Boolean>
TaskObserver
次に進むと、の実装はTaskObserver
を格納しAtomicBoolean
ます。これは、最初はfalseに設定する必要があります。メソッドの本体は、渡された結果がtrueの場合、をfalseからtruecompleted(boolean)
に設定しようとする必要があります。falseからtrueへの移行が成功した場合は、をシャットダウンして、それ以上のタスクの送信を停止します。へのその後の呼び出しは、すでに送信されていて、キャンセル要求に応じるには遠すぎたタスクから発信されます。AtomicBoolean
completed(boolean)
ExecutorService
TaskObserver
public void complete(boolean result)
{
if (result &&
latch_.compareAndSet(false, true))
{
// Set a flag to cease submitting new tasks.
service_.shutdownNow();
if (!service_.awaitTermination(timeoutMagnitude, timeoutUnit))
{
// Report a problem in shutting down the pool in a timely manner.
}
}
}
それだけでは始められない場合は、追加の質問でフォローアップしてください。