ExecutorService, как ждать завершения всех задач - PullRequest
176 голосов
/ 17 июля 2010

Какой самый простой способ дождаться завершения всех заданий ExecutorService? Моя задача в основном вычислительная, поэтому я просто хочу запустить большое количество заданий - по одному на каждое ядро. Прямо сейчас моя установка выглядит так:

ExecutorService es = Executors.newFixedThreadPool(2);
for (DataTable singleTable : uniquePhrases) {   
    es.execute(new ComputeDTask(singleTable));
}
try{
    es.wait();
} 
catch (InterruptedException e){
    e.printStackTrace();
}

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

uniquePhrases содержит несколько десятков тысяч элементов. Должен ли я использовать другой метод? Я ищу что-то максимально простое

Ответы [ 14 ]

1 голос
/ 29 апреля 2016

Отправьте свои задачи в Runner , а затем дождитесь вызова метода waitTillDone () следующим образом:

Runner runner = Runner.runner(2);

for (DataTable singleTable : uniquePhrases) {

    runner.run(new ComputeDTask(singleTable));
}

// blocks until all tasks are finished (or failed)
runner.waitTillDone();

runner.shutdown();

Чтобы использовать его, добавьте этот gradle / mavenЗависимость: 'com.github.matejtymes:javafixes:1.0'

Для более подробной информации смотрите здесь: https://github.com/MatejTymes/JavaFixes или здесь: http://matejtymes.blogspot.com/2016/04/executor-that-notifies-you-when-task.html

0 голосов
/ 19 апреля 2015

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

public static void main(String[] args) {
    // the default `commonPool` should be sufficient for many cases.
    ForkJoinPool pool = ForkJoinPool.commonPool(); 
    // The root of your task that may spawn other tasks. 
    // Make sure it submits the additional tasks to the same executor that it is in.
    Runnable rootTask = new YourTask(pool); 
    pool.execute(rootTask);
    pool.awaitQuiescence(...);
    // that's it.
}

Прелесть в pool.awaitQuiescence, где метод будет блокировать использование потока вызывающейвыполнить свои задачи и затем вернуться, когда оно действительно пусто.

0 голосов
/ 10 февраля 2014

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

 try {  
         //do stuff here 
         exe.execute(thread);
    } finally {
        exe.shutdown();
    }
    boolean result = exe.awaitTermination(4, TimeUnit.HOURS);
    if (!result)

    {
        LOGGER.error("It took more than 4 hour for the executor to stop, this shouldn't be the normal behaviour.");
    }
0 голосов
/ 12 августа 2012

Простая альтернатива этому - использовать потоки вместе с соединением.См .: Присоединительные темы

...