ExecutorService, как узнать, когда все потоки закончились, не блокируя основной поток? - PullRequest
6 голосов
/ 20 марта 2012

У меня есть многопоточная реализация, где я создаю ExecutorService и отправляю задачи для выполнения, я хочу знать, когда все потоки были завершены, не блокируя основной поток и пользовательский интерфейс.Я пробовал ExecutorService.awaitTermination(), но он блокирует основной поток и пользовательский интерфейс.Я много искал, но не могу найти элегантный способ сделать это.В настоящее время я думаю о создании другого потока, который подсчитывает количество завершенных потоков и запускает событие, когда они все закончатся, но это не является хорошим подходом, и я хотел найти лучшее решение!

Ответы [ 5 ]

7 голосов
/ 20 марта 2012

Используйте SwingWorker, чтобы отключить пул потоков и вызвать awaitTermination().Это предотвратит блокирование пользовательского интерфейса и вызовет done() из потока отправки событий в вашей реализации SwingWorker, который вы можете использовать для запуска любых необходимых изменений пользовательского интерфейса.

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

4 голосов
/ 20 марта 2012

Почему бы не использовать CountDownLatch, а затем уведомить основной поток о завершении защелки.

2 голосов
/ 29 ноября 2012

Использование CountDownLatch


CountDownLatch latch = new CountDownLatch(totalNumberOfTasks);
ExecutorService taskExecutor = Executors.newFixedThreadPool(4);
while(...) {
  taskExecutor.execute(new MyTask());
}

try {
  latch.await();
} catch (InterruptedException E) {
   // handle
}

и в пределах вашей задачи (заключите в try / finally)

latch.countDown();

Или в ExecutorService вы вызываете shutdown (), а затемawaitTermination ()

ExecutorService taskExecutor = Executors.newFixedThreadPool(4);
while(...) {
  taskExecutor.execute(new MyTask());
}
taskExecutor.shutdown();
try {
  taskExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
  ...
}

Также взгляните на ЭТО ответ

2 голосов
/ 06 апреля 2012

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

    final ExecutorService execSvc = ...;
    execSvc.submit(task1);
    ...
    execSvc.submit(taskN);
    // important to request the exec service to shut down :)
    execSvc.shutdown();

    new Thread(new Runnable() {

        public void run() {
            while (!execSvc.isTerminated()) {
                try {
                    execSvc.awaitTermination(60, TimeUnit.SECONDS);
                } catch (InterruptedException e) {
                    // ignore exception
                }
            }
            System.out.println("ExecSvc.run: exec service has terminated!");
            // possibly submit a task using SwingUtilities.invokeLater() to update the UI
        }

    }).start();
2 голосов
/ 20 марта 2012

isTerminated() сделает

, однако отметит, что и awaitTermination, и isTerminated дадут вам значимый результат только после того, как вы позвоните shutdown

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