После метода main()

244
25 декабря 2018, 08:10

Появился такой вопрос.

public final class Launcher {
      public static void main(String[] args) {
            // create and run many threads...
      }
}

При запуске приложения внутри main() создается и запускается куча потоков и главный поток не дожидается их завершения (нет join()). Эти потоки делают что-то тяжелое. Главный поток уже вышел из main(). Что теперь делает jvm? Я знаю, что она дожидается всех потоков не демонов. Мне интересно делает ли она что-то для своего завершения? Или просто ждет? Видел, что появляется поток DestroyJavaVM, он для чего?

И что делать, если хочется после выхода из main() убить приложение? Запустить thread-таймер, который при этом демон и в нём сделать System.exit(0)? Нормальное ли это решение?

Стопроцентно ли System.exit(0) убивает jvm? Или есть случаи, когда exit может повиснуть? Если, например, shutdownHook делает что-то тяжелое, то jvm будет его ждать? В каких случаях shutdownHook вообще не дергается (помимо Runtime.halt() и kill -9)?

Извиняюсь за кучу вопросов, но просто много чего непонятно и найти инфу сложно. Все одно и тоже пишут.

Answer 1

После метода main() приложение обычно завершает работу, если оно работает в однопотоковом режиме. Если вы запускаете потоки, то после выхода из main() потоки продолжают работать пока не завершатся или же будут остановлены каким нибудь способом легальным или нелегальным, как например Thread.stop().

Заставляет поток прекратить выполнение.

Deprecated. Этот метод по своей сути является небезопасным. Остановка потока с помощью Thread.stop заставляет его разблокировать все мониторы, которые он заблокировал (как естественное следствие неконтролируемого исключения ThreadDeath, распространяющегося по стеку). Если какой-либо из объектов, ранее защищенных этими мониторами, находился в противоречивом состоянии, поврежденные объекты становятся видимыми для других потоков, что может привести к произвольному поведению. Многие применения stop должны быть заменены кодом, который просто изменяет некоторую переменную, чтобы указать, что целевой поток должен прекратить работу. Целевой поток должен регулярно проверять эту переменную и возвращаться из метода запуска упорядоченным способом, если переменная указывает, что она должна прекратиться. Если целевой поток ожидает длительные периоды (например, при переменной условия), для прерывания ожидания следует использовать метод interrupt. Дополнительные сведения см. В разделе Почему Thread.stop, Thread.suspend и Thread.resume устарели ?.

Так что вам никак не завершить JVM пока вы не остановите потоки. Способ остановки потоков указан в описании устаревшего метода остановки потока. Если вы запускаете потоки по новому, т.е. через ExecutorService то там есть метод для остановки потоков. Более подробно можно почитать здесь.

READ ALSO
Чем заменить PageRequest ? {deprecated}

Чем заменить PageRequest ? {deprecated}

Spring официальная инфа

202
Получить значения из Collections<?> и сохранить их в List

Получить значения из Collections<?> и сохранить их в List

циклом forEach беру value из Collections и добавляю их в List

180
Для чего нужен Eager в связке с Lazy?

Для чего нужен Eager в связке с Lazy?

Был на собеседовании и задали такой вопрос:

172
JPA Repository Max &amp; Min values

JPA Repository Max & Min values

Есть репозиторий:

203