Я читал об этом совсем немного в последние пару часов, и я просто не вижу никаких оснований ( действительна причина) для вызова shutdown()
на ExecutorService
, если мы не будем иметь Humongous приложение , которое хранит, десятки и десятки различных услуг ИСПОЛНИТЕЛЬ, которые не используются для долго.
Единственное (из того, что я понял) завершение работы - это делать то, что делает обычный поток после завершения. Когда обычный поток завершит выполнение метода Runnable (или Callable), он будет передан в сборку мусора для сбора. С Executor Service потоки будут просто приостановлены, они не будут отмечены для сборки мусора. Для этого нужно отключение.
Хорошо, вернемся к моему вопросу. Есть ли причина вызывать выключение ExecutorService
очень часто или даже сразу после отправки ему некоторых задач? Я хотел бы оставить случай, когда кто-то это делает, и сразу после этого звонит, awaitTermination()
когда это подтверждается. Как только мы это сделаем, нам придется заново воссоздавать новое ExecutorService
, чтобы сделать то же самое. Разве не идея ExecutorService
повторного использования потоков? Так зачем уничтожать ExecutorService
так быстро?
Разве это не рациональный способ просто создать ExecutorService
(или объединить, в зависимости от того, сколько вам нужно), затем во время работы приложения передать им задачи, как только они появятся, а затем при выходе из приложения или на некоторых других важных этапах выключить эти исполнители ?
Я хотел бы получить ответ от опытных программистов, которые пишут много асинхронного кода с помощью ExecutorServices.
Второй побочный вопрос, немного поменьше, касается платформы Android. ЕСЛИ некоторые из вас скажут, что отключать исполнителей каждый раз - не лучшая идея, и вы программируете на Android, не могли бы вы рассказать мне, как вы справляетесь с этими отключениями (чтобы быть конкретными - когда вы их выполняете), когда мы имеем дело с различными событиями жизненный цикл приложения.
Из-за комментария CommonsWare я сделал сообщение нейтральным. Мне действительно неинтересно спорить об этом до смерти, и, похоже, это ведет к этому. Мне интересно узнать о том, о чем я здесь просил, опытных разработчиков, только если они готовы поделиться своим опытом. Благодарю.
источник
Ответы:
shutdown()
Метод делает одну вещь: не позволяет клиентам отправлять больше работы службы исполнителя. Это означает, что все существующие задачи по-прежнему будут выполняться до завершения, если не будут предприняты другие действия. Это верно даже для запланированных задач, например, для ScheduledExecutorService: новые экземпляры запланированной задачи не запускаются. Это может быть полезно в различных сценариях.Предположим, у вас есть консольное приложение, в котором есть служба-исполнитель, выполняющая N задач. Если пользователь нажимает CTRL-C, вы ожидаете, что приложение завершится, возможно, изящно. Что это значит изящно? Возможно, вы хотите, чтобы ваше приложение не могло отправлять больше задач в службу исполнителя, и в то же время вы хотите дождаться завершения существующих N задач. Вы можете добиться этого, используя в крайнем случае ловушку выключения:
final ExecutorService service = ... // get it somewhere Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { @Override public void run() { System.out.println("Performing some shutdown cleanup..."); service.shutdown(); while (true) { try { System.out.println("Waiting for the service to terminate..."); if (service.awaitTermination(5, TimeUnit.SECONDS)) { break; } } catch (InterruptedException e) { } } System.out.println("Done cleaning"); } }));
Этот перехватчик завершит работу службы, что не позволит вашему приложению отправлять новые задачи, и дождаться завершения всех существующих задач, прежде чем закрывать JVM. Завершение ожидания будет заблокировано на 5 секунд и вернет истину, если служба отключена. Это выполняется в цикле, чтобы вы были уверены, что служба в конечном итоге отключится. InterruptedException проглатывается каждый раз. Это лучший способ отключить службу-исполнитель, которая повторно используется во всем вашем приложении.
Этот код не идеален. Если вы не абсолютно уверены, что ваши задачи в конечном итоге завершатся, вы можете подождать заданный тайм-аут, а затем просто выйти, оставив работающие потоки. В этом случае имеет смысл также вызвать
shutdownNow()
после тайм-аута в последней попытке прервать запущенные потоки (shutdownNow()
также будет предоставлен список задач, ожидающих выполнения). Если ваши задачи предназначены для реагирования на прерывания, это будет работать нормально.Другой интересный сценарий - это когда у вас есть ScheduledExecutorService, который выполняет периодическую задачу. Единственный способ остановить цепочку периодических задач - позвонить
shutdown()
.РЕДАКТИРОВАТЬ: Я хотел бы добавить, что я бы не рекомендовал использовать крючок выключения, как показано выше, в общем случае: он может быть подвержен ошибкам и должен использоваться только в крайнем случае. Более того, если у вас зарегистрировано много обработчиков выключения, порядок их запуска не определен, что может быть нежелательным. Я предпочел бы иметь приложение явно вызвать
shutdown()
наInterruptedException
.источник
shutdown()
его, чтобы не тратить ресурсы, когда они не нужны. Если приложение завершает работу, потоки в пуле в конечном итоге будут собираться мусором (по умолчанию после того, как они простаивают в течение 60 секунд). Обратите внимание: если вы хотите, чтобы пул был ограничен или вам нужно другое время жизни потока, вы можетеThreadPoolExecutor
напрямую создать файл.Да. Не следует
ExecutorService
часто разрушать и воссоздавать . Инициализируйте его,ExecutorService
когда вам нужно (в основном, при запуске), и держите его активным, пока вы не закончите с ним.Да. Завершение работы рационально
ExecutorService
на важных этапах, таких как выход из приложения и т. Д.Предположим, что
ExecutorService
он используется в разных Activity в вашем приложении. Каждое действие будет приостанавливаться / возобновляться через разные промежутки времени, и вам все равно понадобится одно дляExecutorService
каждого приложения.Вместо того, чтобы управлять состоянием
ExecutorService
в методах жизненного цикла Activity, переместите управление ExecutorService (создание / завершение работы) в свою настраиваемую службу .Создать
ExecutorService
в Service =>onCreate()
и правильно выключить вonDestroy()
Рекомендуемый способ выключения
ExecutorService
:Как правильно завершить работу java ExecutorService
источник
Справочник
Глава: 14 Страница: 814
источник
Причина вызова shutdown () на ExecutorService
Сегодня я столкнулся с ситуацией, когда мне нужно подождать, пока машина будет готова, прежде чем начать серию задач на этой машине.
Я делаю REST-вызов на эту машину, если я не получаю 503 (Сервер недоступен), значит, машина готова обрабатывать мои запросы. Итак, я жду, пока не получу 200 (Успех) для первого вызова REST.
Есть несколько способов добиться этого, я использовал ExecutorService для создания потока и запланировал его запуск через каждые X секунд. Итак, мне нужно остановить этот поток при условии, проверьте это ...
final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); Runnable task = () -> { try { int statusCode = restHelper.firstRESTCall(); if (statusCode == 200) { executor.shutdown(); } } catch (Exception e) { e.printStackTrace(); } }; int retryAfter = 60; executor.scheduleAtFixedRate(task, 0, retryAfter, TimeUnit.SECONDS);
Второй побочный вопрос, немного поменьше, касается платформы Android.
Может быть, я смогу ответить, если вы предоставите немного больше контекста! Кроме того, по моему опыту разработки под Android, потоки нужны редко. Вы разрабатываете игру или приложение, которому для производительности нужны потоки? Если нет, то в Android у вас есть другие способы решения проблем, такие как сценарий, который я объяснил выше. Вы можете использовать TimerTask, AsyncTask или обработчики или загрузчики в зависимости от контекста. Это потому, что если UIThread ждет долго, вы знаете, что произойдет: /
источник
Это справедливо, несмотря на то, что запланированные мероприятия, например, для ScheduledExecutorService: новые случаи зарезервированного задания не запускаются.
Мы должны ожидать, что у вас есть удобное приложение, в котором администрирование агента выполняет N поручений.
Я не улавливаю это без усилий? Возможно, вам нужно, чтобы ваше приложение не имело возможности отправлять дополнительные задания администрации агента, а тем временем вам нужно дождаться завершения ваших текущих N обязательств.
За исключением случаев, когда вы полностью уверены, что ваши дела в конце концов будут выполнены, вам нужно будет сидеть спокойно в течение определенного перерыва, а после этого просто выйти, оставив бегающие струны.
Если ваши действия предназначены для реагирования на вмешательство, это будет нормально работать.
Еще одна интригующая ситуация - это момент, когда у вас есть ScheduledExecutorService, который разыгрывает действие.
Лучший способ остановить цепочку действий - вызвать shutdown ()
источник