Подтвердить что ты не робот

Темы демона, запланированные на ExecutorService; объясните, почему это плохая форма

Мне нравится идея упорядоченного выключения на потоках, запланированных с помощью ExectuorService; то есть вызов shutdown или shutdownNow заставит потоки, созданные в пуле, выйти изящно. Если они отвечают на interrupt, вы можете быть уверены, наконец, и т.д. Вызывается, и вы получите чистый, предсказуемый выход (где вы можете очистить любые ресурсы и т.д.).

Однако, если вы установили поток в качестве демона (через исполнителя ThreadFactory), как показано ниже.

ExecutorService pool = Executors.newSingleThreadExecutor(new ThreadFactory() {
   @Override
   public Thread newThread(Runnable runnable) {
      Thread thread = Executors.defaultThreadFactory().newThread(runnable);
      thread.setDaemon(true);
      return thread;
   }
});

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

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

Почему это плохая практика (или нет, если вы не согласны) использовать потоки демона в пуле потоков ExecutorService? В частности, я заинтересован в описании жизненного цикла выключения VM с изящным отключением (потоки, которые имеют политику прерывания и хорошо играют) против потоков демонов.

Развернув эту последнюю точку, finalize на ThreadPoolExecutor вызовет shutdown сам по себе, но когда он будет использовать потоки демона, они могли бы прекратить свое существование, если виртуальная машина вызвала finalize. Каково поведение пула потоков? Может ли он быть обманутым в оставшемся живым (и, следовательно, не выходящим из ВМ), если основные потоки прекратились внезапно?

Часть причины, о которой я прошу, заключается в том, что я видел, что она использовалась для обхода необходимости закрытия существующего ExectorService. Можете ли вы придумать сценарии, в которых обход его жизненного цикла останова может сильно повлиять? Пока единственная причина, по которой я могу придумать использование демонов, - это короткое сокращение, и я хочу оценить любые неожиданные побочные эффекты, которые это может вызвать.

4b9b3361

Ответ 1

Неправильно ли использовать потоки демона в пуле потоков ExecutorService?

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

finalize() вызывается, когда объект собирается собирать мусор. Нет никаких гарантий того, когда когда-либо какой-либо конкретный объект будет GCd, а ThreadPoolExecutor не является исключением, поэтому его finalize() может быть вызван или не может быть вызван. Поведение зависит от конкретной реализации JRE и даже с той же реализацией, время от времени может меняться.

Ответ 2

Я имею тенденцию иметь разные пулы для потоков daemon и non-daemon. В пулах Daemon обычно повторяются задачи очистки, мониторинга и фоновых задач, которые не имеют значения, если один или два не выполняются. Любая задача, которая имеет смысл только во время работы приложения, хороша для выполнения задачи потока демона. например Потоки GC - это потоки демона.

Ответ 3

Темы демона могут быть полезны, и если они не прекращаются внезапно, они не будут столь полезными ИМО.

Предположительно мы могли бы представить себе другой тип потока, который прерывается, когда нормальные потоки не работают больше, вместо того, чтобы внезапно прекращаться. Это может быть немного удобно, но если вам вообще нужно было очистить, скорее всего, вы захотите сделать аккуратную уборку. Это ограничило бы удобство этой функции.

С другой стороны, если у вас были задачи, которые не нуждались бы в очистке при выключении, потоки деамонов вполне удобны. И вы не хотели бы тратить время, ожидая их, чтобы добраться до какого-то определенного состояния, или рискуете повесить трубку при выключении и т.д., Потому что причина, по которой вы используете поток деамонов, состоит в том, что вам не нужна какая-либо очистка. Было бы пустой тратой времени на выполнение чего угодно, если приложение. закрывается. Если вам все равно, тогда вы не должны были использовать темы деамонов.

Ничем не отличается от пулов демона. Если этот пул потоков выполняет задачи, которые не нуждаются в очистке при выключении, тогда это будет иметь смысл из-за удобства.

Из JCiP book:

Нитки Daemon следует использовать экономно, но некоторые виды обработки могут быть безопасно оставлены в любой момент без очистки. В частности, опасно использовать потоки демона для задач, которые могут выполнять какие-либо операции ввода-вывода. Темы демона лучше всего сохраняются для задач "домашнего хозяйства", таких как фоновый поток, который периодически удаляет истекшие записи из кэша в памяти