Параллельно ли выполняются задачи при выполнении через ExecutorCompletionService? - PullRequest
1 голос
/ 26 июня 2009

Я отправил 5 заданий на ExecutorCompletionService , но кажется похожим на задания, выполняемые последовательно. ExecutorService, который передается конструктору ExecutorCompletionService , создается с помощью формы newCacheThreadPool. Я делаю что-то не так?

ОБНОВЛЕНИЕ Каждая работа в основном выполняет запрос к базе данных и некоторые вычисления. Код для ExecutorCompletionService снят как есть с Javadoc. Я только заменил Callables своими собственными реализациями Callable.

Ответы [ 4 ]

4 голосов
/ 26 июня 2009

ExecutorCompletionService не имеет отношения к выполнению заданий, это просто удобный способ получения результатов.

Executors.newCachedThreadPool по умолчанию выполняет задачи в отдельных потоках, которые могут быть параллельными, учитывая, что:

  • задачи являются независимыми и, например, не синхронизировать на одном и том же объекте внутри;
  • у вас есть несколько аппаратных потоков процессора.

Последний пункт заслуживает объяснения. Хотя никаких гарантий нет, на практике Sun JVM предпочитает текущий выполняемый поток, поэтому он никогда не заменяется другим. Это означает, что ваши 5 задач могут в конечном итоге выполняться последовательно из-за реализации JVM и не иметь, например, многоядерный станок.

1 голос
/ 28 июня 2009

Каждая работа в основном выполняет запрос к базе данных и некоторые вычисления. Код для ExecutorCompletionService снят как есть с Javadoc. Я только заменил Callables своими собственными реализациями Callable.

В этом случае вы уверены, что не ошибаетесь, думая, что они выполнены последовательно, потому что вы извлекаете результаты последовательно?
Добавьте некоторые строки журнала отладки в ваши вызовы, чтобы исключить это, и / или посмотрите на этот сценарий ограниченного использования:

public static void main(String... args) throws InterruptedException, ExecutionException {
    List<Callable<String>> list = new ArrayList<Callable<String>>();
    list.add(new PowersOfX(2));
    list.add(new PowersOfX(3));
    list.add(new PowersOfX(5));
    solve(Executors.newCachedThreadPool(), list);
}

static void solve(Executor e, Collection<Callable<String>> solvers) throws InterruptedException, ExecutionException {
    CompletionService<String> ecs = new ExecutorCompletionService<String>(e);
    for (Callable<String> s : solvers)
        ecs.submit(s);
    int n = solvers.size();
    for (int i = 0; i < n; ++i) {
        String r = ecs.take().get();
        if (r != null)
            System.out.println("Retrieved: " + r);
    }
}

static class PowersOfX implements Callable<String> {
    int x;
    public PowersOfX(int x) {this.x = x;}
    @Override
    public String call() throws Exception {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 10; i++) {
            sb.append(Math.pow(2, i)).append('\t');
            System.out.println(Math.pow(x, i));
            Thread.sleep(2000);
        }
        return sb.toString();
    }
}

При выполнении этого вы увидите, что числа генерируются смешанными (и, следовательно, выполняются одновременно), но получение только результатов не покажет вам детали этого уровня ..

1 голос
/ 26 июня 2009

Полагаю, вы имели в виду Executors.newCachedThreadPool () . Если это так, выполнение должно быть распараллелено, как вы ожидаете.

0 голосов
/ 26 июня 2009

Исполнение будет зависеть от ряда вещей. Например:

  • время, необходимое для выполнения задания
  • количество потоков в пуле потоков (кэшированный пул потоков будет создавать потоки только в том случае, если он считает, что они необходимы)

Выполнение в последовательности не обязательно является неправильным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...