ThreadPool/Executor как для Runnable, так и для Callable - который может автоматически выходить из java8

Я пытаюсь использовать ThreadPoolExecutor/ExecutorService в своем приложении - это статический глобальный объект. Я использую: Executors.newScheduledThreadPool(corePoolSize) - но у меня проблемы с закрытием executorService.

Если я не вызову shutdown() + awaitTermination(), мое приложение не завершится, даже если все потоки будут завершены.

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

Есть ли способ разрешить java shutdown() службу исполнителя, когда все потоки будут завершены.

Спасибо

-- Также этот вопрос не является дубликатом - исправление демона заставляет мое приложение завершать работу до того, как все потоки будут завершены (см. комментарий) - Какое будет исправление для этого? Спасибо


person EKK    schedule 16.03.2015    source источник
comment
Не полный дубликат. Создание демонов всех потоков приведет к завершению работы приложения, как только появится основной поток, а не сразу после завершения задач, как спрашивает OP.   -  person GPI    schedule 16.03.2015
comment
Правильно - я только что попробовал это решение, и оно выходит, не выполнив все задачи. Что бы исправить?   -  person EKK    schedule 16.03.2015
comment
Очень общий вопрос, который поможет нам ответить: можете ли вы указать в своем вопросе, как вы узнали, что отправили все задачи исполнителю? (Возможно, у вас есть фиксированное количество задач, которые отправляют известное количество вызываемых объектов в вашем исполнителе, или, возможно, каждая из этих задач диспетчеризации может знать, когда они сами завершились...)   -  person GPI    schedule 16.03.2015
comment
Если запустить Task1 и кикнуть Task2 и Task3 - на каком-то этапе будут завершены task2 и task3 - а значит их поток будет завершен. Тогда, если задача 1 не делает ничего, кроме запуска задачи 2 и задачи 3, тогда задача 1 также будет завершена, поэтому знание того, какая задача завершена, где-то есть, и я не думаю, что мне нужно иметь с этим дело. Это?   -  person EKK    schedule 16.03.2015
comment
Если сделать awaitTermination, то выключение, в чем проблема?   -  person Bram    schedule 16.03.2015
comment
@EKK: нет, логики там нет. С точки зрения ExecutorService, если Task2 работает супер-супер-быстро и завершается еще до того, как вы отправите Task3, то, по вашему определению, он должен остановиться после Task2. (Мой пример - преувеличение, но концепция такова: нет, ExecutorService не знает, сделано ли это, только вы можете знать определение готовности)   -  person GPI    schedule 16.03.2015
comment
Проблема в том, что некоторые потоки пинают другие потоки после вызова завершения работы.   -  person EKK    schedule 16.03.2015
comment
@ GP1: если все потоки завершены, а основной поток находится в последней строке - больше потоков не может быть отправлено - тогда ExecutorService больше никогда не получит отправленных задач. В то же время timerTasks (запуск другого задания исполнителю) могли быть созданы вне ExecutorService — и исполнитель об этом не знает. В общем, я не могу знать, завершены ли потоки, которые я отправил исполнителю, а исполнитель не знает, что происходит снаружи, поэтому мы оба не знаем...   -  person EKK    schedule 16.03.2015
comment
@EKK: если вы, разработчик, не можете знать, компьютер не может знать, конец истории :(. Поэтому я могу посоветовать вам использовать (Singleton?) ConcurrentList, который будет отслеживать все фьючерсы вашей задачи и пытаться get их проверьте, выполнено ли это Я мог бы посоветовать вам использовать AtomicInteger для подсчета количества активных задач таймеров, я мог бы посоветовать вам использовать Semaphore или CountDownLatch, чтобы ваши потоки могли сигнализировать, когда они выполняются коллективно... Но ничего из этого будет полезно до тех пор, пока вы не знаете, как определить, что вы закончили... (Таймеры больше не будут срабатывать? Все таймеры сделаны?)   -  person GPI    schedule 16.03.2015
comment
@GPI: кажется, что CachedThreadPool достаточно умен, чтобы понять это - посмотрите пример в: stackoverflow.com/questions/29098117/   -  person EKK    schedule 17.03.2015
comment
Это простая реализация тайм-аута. Но это не ScheduledThreadPool, как указывает ваш вопрос. Если это работает для вас, тогда хорошо (и это означает, что ваше определение выполнено: если ни одна задача не была отправлена ​​​​в течение 1 минуты, что является тайм-аутом потока CachedThreadPool). Однако будьте осторожны с corePoolSize, потому что, если он не равен нулю, у вас все равно будут живые потоки. Это все детали реализации, которые могут вам подойти, но вы должны знать, как это соотносится с вашими бизнес-требованиями.   -  person GPI    schedule 17.03.2015
comment
Разве вы не можете использовать Runtime.getRuntime().registerShutdownHook() для регистрации ваших потоков отключения?   -  person Ferrybig    schedule 13.01.2016