Почему ShutdownHookThread ‘setDaemon true’

#java #multithreading #scala #shutdown-hook

#java #многопоточность #scala #shutdown-hook

Вопрос:

Недавно мне нужно было добавить перехват завершения работы в приложение Scala, которое у меня есть, и я обнаружил, что Scala предоставляет для этого помощник под названием ShutdownHookThread. В его исходном коде я заметил, что он устанавливает новый поток как поток демона.

 def apply(body: => Unit): ShutdownHookThread = {
  val t = new ShutdownHookThread(hookName()) {
    override def run() = body
  }
  t setDaemon true  // <--------- right here
  runtime addShutdownHook t
  t
}
  

Почему это делается? Мне кажется, вы, вероятно, хотели бы обратного в потоке подключения к завершению работы (т. Е. Убедитесь, что поток завершается перед завершением работы jvm). Или демон / не демон не имеет отношения к перехватам завершения работы?

Комментарии:

1. Не знаю, почему, это по умолчанию в фреймворке — плохая идея. Вы правы, задавая этот вопрос, для обычного языка Java ShutdownHooks не демонизируются. Но я бы согласился с тем, что разработчик приложения должен сделать выбор в пользу демонизации (если он лучше знает, чего пытается достичь этот поток, и действительно хочет такого поведения, мне все равно, если я запущу). Итак, чтобы быть уверенным, что это 100% ошибка, вам нужно уточнить, если / как ShutdownHooks сериализуются при завершении работы JVM. Если они сериализуют run / join, то установка Daemonize всегда является ошибкой.

Ответ №1:

В JVM, как правило, поток, не являющийся демоном, предотвращает завершение работы JVM. Как только больше не будет потоков, отличных от демонов, JVM завершит работу, инициировав завершение работы. См. addShutdownHook javadoc для получения дополнительной информации.

После завершения работы я не уверен, что статус демона имеет значение. Также потоки перехвата завершения работы не запускаются до тех пор, пока не будет инициировано завершение работы. Так что в этом случае t setDaemon true может быть ненужным, но это тоже не повредит.

Итак, короче говоря, семантика «демона» отличается от unix (где в unix land это обозначает поток, который продолжает выполняться).

Комментарии:

1. Спасибо за ответ. Вы говорите: «в общем, поток демона предотвратит завершение работы JVM». Мое понимание противоположно (исходя из этого ). Если в приложении остались только потоки демонов, JVM завершит работу. Итак, если ваш основной (не демонический) поток заканчивается, а ваши перехваты завершения работы имеют значение daemon= true, вы можете выйти до их запуска. Если только все это не имеет значения после инициализации завершения работы.

2. @overthink, да, полная опечатка. просто исправлено, так что теперь первое предложение фактически соответствует второму предложению! спасибо за исправление. Что касается вашего последнего предложения, это действительно то, что я думаю. «ничто из этого не имеет значения после инициализации завершения работы». Я думаю, это нужно было бы протестировать или поискать в Google для подтверждения.

3. Подумал, что это может быть опечатка. Спасибо за разъяснения!

Ответ №2:

Отвечая на мой собственный вопрос здесь.

Две части:

  1. Почему ShutdownHookThread делает свои новые потоки daemon=true?
  2. Что происходит, если поток подключения завершения работы имеет значение daemon= true?

Ответы:

  1. Это связано с требованиями к «Scala scripting» (запуск scala myfile.scala , а не явная компиляция сначала). Обсуждение здесь. Теперь он был изменен (зафиксирован), поэтому в будущих версиях ShutdownHookThread этого кода не будет.
  2. Я не нашел ничего решающего, но экспериментально это, похоже, не имеет значения. Я думаю, это имеет смысл, поскольку статус демона влияет на то, когда JVM начнет завершение работы, поэтому после завершения работы статус демона не должен иметь значения.