Подтвердить что ты не робот

Как дождаться появления списка `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` ``

Хорошо, поэтому я знаю, что первый ответ/комментарий здесь будет "использовать один ExecutorService и использовать invokeAll". Тем не менее, есть веская причина (с которой я не буду скучать), поскольку мы сохраняем отдельные пулы потоков.

Итак, у меня есть список пулов потоков (ExecutorServices), и мне нужно сделать другой Callable в каждом пуле потоков с помощью submit (там нет проблем). Теперь у меня есть коллекция экземпляров Future, каждая из которых создана на отдельном ExecutorService, и я хочу дождаться, когда все они будут завершены ( и сможет предоставить тайм-аут, в который отменены любые неработающие).

Есть ли существующий класс, который сделает это (завершите список экземпляров Future и разрешите ждать, пока все не будут выполнены)? Если нет, предложения по эффективному механизму будут оценены.

Думал о вызове get с тайм-аутом для каждого, но ему нужно сделать расчет общего времени, прошедшего для каждого вызова.

Я видел этот пост Подождите, пока не будет выполнено какое-либо будущее, но это расширяет Future вместо того, чтобы обернуть список из них.

4b9b3361

Ответ 1

В комментарии Луи, я искал Futures.successfulAsList

Это позволяет мне дождаться завершения всех, а затем проверить, не сработали ли какие-либо фьючерсы.

Guava ПРАВИЛА!

Ответ 2

Я не думаю, что JDK предоставляет прямой API, который позволяет вам это делать. Однако, я думаю, что так же просто создать простой метод, который делает это. Вы можете взглянуть на реализацию AbstractExecutorService.invokeAll(), чтобы понять, что это можно сделать.

По сути, вы бы назвали future.get() в каждом будущем, уменьшив время ожидания на время, затрачиваемое на ожидание результата каждый раз, и перед возвратом из метода отмените все выдающиеся фьючерсы.

Ответ 3

Возможно, я действительно не понял. Однако для меня это звучит так же просто, как

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;
}

Неужели я ошибаюсь?

Вопрос, который вы связываете, намного сложнее, я думаю, поскольку они только хотят дождаться самого быстрого и, конечно, не имеют представления, что будет самым быстрым.

Ответ 4

Это может использовать некоторую очистку, но это должно решить вашу проблему. (Некоторая инкапсуляция опущена для времени и пространства):

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]
}