12

わかりましたので、ここでの最初の回答/コメントは「使用ExecutorServiceして使用するinvokeAll」になることを知っています。ただし、スレッド プールを個別に保持するのには十分な理由があります (人々を退屈させるつもりはありません)。

したがって、スレッドプールのリスト( )があり、使用するスレッドプールごとExecutorServicesに異なるものを呼び出す必要があります(問題ありません)。これで、このインスタンスのコレクションがあり、それぞれが個別に作成され、すべてが完了するのを待ちたい (そして、完了していないものがキャンセルされるタイムアウトを提供できるようにする)。CallablesubmitFutureExecutorService

これを行う既存のクラスはありますか (Futureインスタンスのリストをラップし、すべてが完了するまで待機できるようにします)? そうでない場合は、効率的なメカニズムに関する提案をいただければ幸いです。

それぞれにタイムアウトを指定して呼び出すことを考えgetていましたが、呼び出しごとに経過した合計時間を計算する必要があります。

この投稿を見ました将来のいずれかが完了するまで待機しFutureます しかし、これはそれらのリストをラップする代わりに拡張されます。

4

4 に答える 4

17

Louis のコメントによると、私が探していたのはFutures.successfulAsList でした

これにより、すべてが完了するのを待ってから、失敗した先物を確認できます。

グアバのルール!

于 2012-11-02T09:55:04.757 に答える
2

JDKがそれを可能にする直接APIを提供しているとは思いません。ただし、これを行う簡単なメソッドを作成することも同様に簡単だと思います。AbstractExecutorService.invokeAll()の実装を調べて、これが実行できることを理解することをお勧めします。

基本的に、future.get()を各futureで呼び出し、待機時間を毎回結果を待つのにかかる時間だけ減らし、メソッドから戻る前にすべての未処理のfutureをキャンセルします。

于 2012-11-01T20:01:38.253 に答える
1

これにはクリーンアップが必要になる可能性がありますが、問題は解決するはずです。(時間と空間のために省略された一部のカプセル化):

public static <T> LatchWithWrappedCallables<T> wrapCallables(Collection<Callable<T>> callablesToWrap)
{
    CountDownLatch latch = new CountDownLatch(callablesToWrap.size());
    List<Callable<T>> wrapped = new ArrayList<Callable<T>>(callablesToWrap.size());
    for (Callable<T> currCallable : callablesToWrap)
    {
        wrapped.add(new CallableCountdownWrapper<T>(currCallable, latch));
    }

    LatchWithWrappedCallables<T> returnVal = new LatchWithWrappedCallables<T>();
    returnVal.latch = latch;
    returnVal.wrappedCallables = wrapped;
    return returnVal;
}

public static class LatchWithWrappedCallables<T>
{
    public CountDownLatch latch;
    public Collection<Callable<T>> wrappedCallables;
}

public static class CallableCountdownWrapper<T> implements Callable<T>
{
    private final Callable<T> wrapped;

    private final CountDownLatch latch;

    public CallableCountdownWrapper(Callable<T> wrapped, CountDownLatch latch)
    {
        this.wrapped = wrapped;
        this.latch = latch;
    }

    @Override
    public T call() throws Exception
    {
        try
        {
            return wrapped.call();
        }
        finally
        {
            latch.countDown();
        }
    }
}

次に、コードは次のように呼び出します。

Collection<Callable<String>> callablesToWrap = [Your callables that you need to wait for here];
LatchWithWrappedCallables<String> latchAndCallables = wrapCallables(callablesToWrap);

[Submit the wrapped callables to the executors here]

if(latchAndCallables.latch.await(timeToWaitInSec, TimeUnit.SECONDS))
{
    [Handling for timeout here]
}
于 2012-11-01T20:45:57.693 に答える
1

たぶん、私は本当にそれを理解していませんでした。ただし、私にはまだ次のように単純に聞こえます

public <V> List<V> get(List<Future<V>> futures, long timeout, TimeUnit unit)
          throws InterruptedException, ExecutionException, TimeoutException {
    List<V> result = new ArrayList<V>();
    long end = System.nanoTime() + unit.toNanos(timeout);
    for (Future<V> f: futures) {
        result.add(f.get(end - System.nanoTime(), TimeUnit.NANOSECONDS));
    }
    return result;
}

私はそれで間違っていますか?

あなたがリンクしている質問は、彼らが最速を待ちたいだけで、もちろんどれが最速になるか分からないので、もっと複雑だと思います。

于 2012-11-01T20:14:11.960 に答える