Я знаю, что shutdown()
и awaitTermination()
есть. Проблема состоит в том, что в пулах в пуле должно быть возможно добавить неизвестное число (не может использовать countdownlatch) других runnables, и если я вызову shutdown()
, эти задачи будут отклонены. Как я могу узнать, когда они будут сделаны?Как узнать, когда все потоки в ExecutorService закончены?
ответ
Вместо отправки Runnable
задач на Executor
, вы должны использовать вместо этого ForkJoinTask
/ForkJoinPool
. A ForkJoinTask
работает внутри ForkJoinPool
и может порождать произвольное количество (под) задач и ждать их завершения, фактически не блокируя текущий поток. A ForkJoinTask
завершен, когда все его подзадачи выполнены, поэтому выполняется полное вычисление, когда начальный (корень) ForkJoinTask
завершен.
Для получения более подробной информации см. Oracle - The Java™ Tutorials - Fork/Join.
Поскольку все ваши задачи являются безрезультатными (Runnable
), вы должны подкласс RecursiveAction
(который сам по себе является подклассом ForkJoinTask
). Внесите метод compute()
и создайте произвольное количество новых задач там, вызывая invoke(subtask)
, invokeAll(subtask1, subtask2, ...)
или subtask.fork()
, а затем subtask.join()
.
Весь расчет выполняется следующим образом:
MyRecursiveAction task = new MyRecursiveAction(params);
ForkJoinPool pool = new ForkJoinPool(numberOfThreads);
pool.invoke(task); // will block until task is done
Unfortunatley преимущества вилки/Join имеют некоторые ограничения, например:
(...) Вычисления в идеале должны избегать синхронизированных методов или блоки и должны минимизировать другую блокирующую синхронизацию, помимо объединения других задач или с использованием синхронизаторов, таких как Phasers, которые рекламируются для сотрудничества с планированием fork/join. Субдивидируемые задачи также должны не выполнять блокировку ввода-вывода и должны идеально обращаться к переменным, которые полностью независимы от тех, к которым выполняются другие запущенные задачи. Эти директивы слабо применяются, если не разрешены проверенные исключения , такие как IOExceptions, которые должны быть выбраны. (...)
Подробнее см. API docs of ForkJoinTask
.
Этот способ лучше всего подходит для ответов. Благодарю. – user2980766
Работает с Future
, а не с Runnable
. Вот этот метод Future#isDone
, который может вам помочь.
Если у вас нет ничего значимого для возврата из Callable
, используйте Callable<Void>
и Future<Void>
.
Если вы в состоянии использовать Guava Futures, вы можете использовать Futures.allAsList
или Futures.successfulAsList
. Это позволяет вам обернуть несколько экземпляров Future
, которые вы получили от ExecutorService
, в один Future
, который затем вы можете проверить, будет ли он закончен с использованием isDone()
(или просто get()
, если на то пошло, если вы хотите заблокировать до завершения).
- 1. ExecutorService, как узнать, когда все потоки закончены без блокировки основного потока?
- 2. Как я узнать, что все потоки в ExecutorService завершили выполнение
- 3. Как обновить main {}, когда потоки закончены?
- 4. Как выйти из программы, когда все потоки закончены?
- 5. Выполнить действие, когда все потоки в основном не закончены? (Python)
- 6. Как определить, когда все методы закончены?
- 7. Есть ли способ узнать, успешно ли ExecutorService?
- 8. Групповые потоки в ExecutorService
- 9. Как прервать потоки ExecutorService
- 10. Изящно завершайся, когда все рабочие закончены
- 11. Как приостановить/возобновить все потоки в ExecutorService в Java?
- 12. Как узнать, когда протрактор/жасмин закончены? (Логика инструмента отчетности)
- 13. Как узнать, когда MKMapView и видимый MKAnnotationView закончены?
- 14. Как вы ограничиваете потоки в ExecutorService?
- 15. Зная, когда актеры акки закончены
- 16. Определение, когда все потоки завершены C#
- 17. Java ExecutorService потоки, написанные в одном поле
- 18. Как установить флаг, указывающий, когда все потоки выполняются
- 19. ExecutorService, который масштабирует потоки, затем ставит задачи
- 20. Как узнать, кто создает все ваши потоки в программе delphi?
- 21. Как запустить код, когда все потоки завершены
- 22. Почему «ExecutorService» не может последовательно создавать потоки?
- 23. Внешнее обслуживание запускает асинхронную задачу и сразу же возвращается. Как узнать, когда задачи действительно закончены?
- 24. Есть ли способ понять, когда все задачи закончены?
- 25. Task Parallel Library - знать, когда все задачи закончены
- 26. Когда запущен объект мусора, собранный в ExecutorService?
- 27. AsyncHttpClient с ThreadPoolExecutor, чтобы узнать, когда все задачи завершены?
- 28. В Java ExecutorService, как установить максимальные потоки, потребляемые по запросу
- 29. Как добавить новые задачи Threadpool только тогда, когда все задачи закончены используя импульс в C++
- 30. Подождите, пока все асинхронный вызова закончены
Когда задача ('Runnable') T порождает другие n задач, вы могли бы сказать, что эта задача T выполняется, когда все эти n задач выполнены? Итак, существует (концептуальная) зависимость между задачей T и ее подзадачами? – isnot2bad
Справа.Я забыл, что я использую 'newFixedThreadPool', где максимальное количество работающих потоков - это количество процессоров. Как только один runnable порождает других, для этого больше не нужно работать. Если бы он ждал, пока исполняемые файлы, которые он породил, закончили, он просто сидит там, ничего не делая, и программа никогда не закончится из-за ограничения количества потоков. – user2980766
Поэтому вы должны, вероятно, использовать 'ForkJoinTask'. – isnot2bad