Фоновый поток в Java
Когда все обычные (user) потоки завершились,
JVM завершает процесс, даже если ещё работают фоновые
daemon потоки. Так устроены служебные задачи:
сборщик мусора, таймеры внутри библиотек. Прикладной
код помечает daemon явно до start().
Метод setDaemon(true) нельзя вызвать на уже
запущенном потоке. Проверка типа - isDaemon().
По умолчанию новый Thread - обычный user
поток.
Фоновый поток с бесконечным циклом не удержит программу:
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread daemon = new Thread(() -> {
while (!Thread.currentThread().isInterrupted()) {
System.out.println("daemon tick");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
}, "bg");
daemon.setDaemon(true);
daemon.start();
Thread.sleep(500);
System.out.println("main ends");
}
}
После выхода из main JVM закроется, не дожидаясь
бесконечного daemon. В консоли может быть несколько
daemon tick, но программа не зависнет.
Тот же цикл как user поток удержал бы процесс, пока его не прервут:
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread user = new Thread(() -> {
while (!Thread.currentThread().isInterrupted()) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}, "user");
user.start();
Thread.sleep(300);
user.interrupt();
user.join();
System.out.println("user stopped");
}
}
Долгую прикладную работу (запись файла, расчёт отчёта)
оформляют user потоком и дожидаются join.
Daemon оставляют для задач, которые можно оборвать вместе
с процессом.
Создайте daemon с sleep(1000) в цикле,
запустите его, выведите из main "bye"
и завершите main без join. Убедитесь,
что процесс завершился, не дожидаясь секундной паузы
daemon.