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

Почему поток перехватывает основной метод в Java?

Я преподавал себе потоки Java, и я заметил кое-что, что меня немного смущает. Я создал класс под названием engine, реализующий Runnable. Метод run просто печатает "Hello World", спит на секунду и повторяет.

В моем основном методе у меня есть:

public static void main(String[] args) {
    Thread thread = new Thread(engine);
    thread.start();
    System.out.println("Done.");
}

Как я и ожидал, я вижу "Hello World" и "Done". напечатанный быстро, что означает, что основной метод дошел до конца, но я не ожидал, что поток, который я начал работать, продолжался даже после того, как был достигнут конец main.

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

4b9b3361

Ответ 1

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

Thread t = new Thread(...);
t.setDaemon(true);

Все потоки не-daemon являются потоками пользователей. Эти потоки останавливают jvm от закрытия.

Ответ 2

Потому что так оно и работает. Программа выходит, когда вызывается System.exit() или когда последний поток не-демона прекращается.

И это имеет смысл. Без этого правила каждая Java-программа, состоящая только в том, чтобы развернуть GUI, например, должна была бы (бесконечно) ждать, чтобы программа немедленно не выходила.

Ответ 3

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

Вызов setDaemon(true) в вашем потоке, прежде чем вы начнете его, сделает ваш процесс завершенным (более или менее), как только ваша функция main() вернется.

Ответ 4

Пользовательские потоки продолжают работать независимо от времени жизни их родительского потока, т.е. потока создателя. Итак, вы должны явно присоединиться к потокам, вызывая Thread.join до того, как поток main завершится.

Из Javadoc Thread:

Когда запускается виртуальная машина Java, обычно имеется один non-daemon thread (который обычно вызывает метод с именем main of some назначенный класс). Виртуальная машина Java продолжает выполнять пока не произойдет одно из следующих действий:

  • Вызывается метод выхода класса Runtime и безопасность менеджер разрешил операцию выхода.

  • Все потоки, которые не являются потоками демона, умерли, либо возвратившись от вызова метода run или путем исключения исключения, которое распространяется за пределы метода run.

Если вы хотите, чтобы JVM завершался, даже если поток t запущен, вы должны сделать поток t потоком демона:

t.setDaemon(true);

Ответ 5

Раздел Java Language Specification раздел 12.8 указывает:

12,8. Выход программы

Программа завершает всю свою деятельность и выходит, когда одна из двух вещей бывает:

Все потоки, которые не являются потоками демона, завершаются.

В некотором потоке вызывается метод exit класса Runtime или класс System, и диспетчер безопасности не запрещает операцию выхода.

Это означает, что для завершения основного потока недостаточно.

Если вы хотите, чтобы он вышел, когда заканчивается главный поток, вам нужно либо сделать новый поток демонами, используя Thread # setDaemon, либо использовать Thread # join, как вы изначально предполагали.

Ответ 6

Основной поток также представляет собой пользовательский поток, который создается, и его жизненный цикл похож на любой другой пользовательский поток. Другие потоки пользователей не зависят от основного потока по какой-либо причине, если вы не установите потоки как потоки демона. Как только основной поток завершает свою работу, он заканчивается (он не заканчивает другие пользовательские потоки и не завершает процесс, потому что выполняются другие пользовательские потоки).