Перейти к основному содержимому

Потоки демона в Java

· 3 мин. чтения

1. Обзор

В этой короткой статье мы рассмотрим потоки демона в Java и посмотрим, для чего их можно использовать. Мы также объясним разницу между потоками демона и пользовательскими потоками.

2. Разница между демоном и пользовательскими потоками

Java предлагает два типа потоков: пользовательские потоки и потоки демона.

Пользовательские потоки — это потоки с высоким приоритетом. JVM будет ждать, пока любой пользовательский поток завершит свою задачу, прежде чем завершить ее.

С другой стороны, потоки демона — это потоки с низким приоритетом, единственная роль которых состоит в предоставлении услуг пользовательским потокам.

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

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

Однако из этого правила есть исключения. Плохо спроектированный код в потоках демона может помешать выходу JVM. Например, вызов Thread.join() в работающем потоке демона может заблокировать завершение работы приложения.

3. Использование потоков демона

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

4. Создание потока демона

Чтобы установить поток как поток демона, все, что нам нужно сделать, это вызвать Thread.setDaemon(). В этом примере мы будем использовать класс NewThread , который расширяет класс Thread :

NewThread daemonThread = new NewThread();
daemonThread.setDaemon(true);
daemonThread.start();

Любой поток наследует статус демона создавшего его потока. Поскольку основной поток является пользовательским потоком, любой поток, созданный внутри основного метода, по умолчанию является пользовательским потоком.

Метод setDaemon() может быть вызван только после того, как объект Thread создан, а поток еще не запущен. Попытка вызвать setDaemon() во время выполнения потока вызовет исключение IllegalThreadStateException :

@Test(expected = IllegalThreadStateException.class)
public void whenSetDaemonWhileRunning_thenIllegalThreadStateException() {
NewThread daemonThread = new NewThread();
daemonThread.start();
daemonThread.setDaemon(true);
}

5. Проверка того, является ли поток потоком демона

Наконец, чтобы проверить, является ли поток потоком демона, мы можем просто вызвать метод isDaemon() :

@Test
public void whenCallIsDaemon_thenCorrect() {
NewThread daemonThread = new NewThread();
NewThread userThread = new NewThread();
daemonThread.setDaemon(true);
daemonThread.start();
userThread.start();

assertTrue(daemonThread.isDaemon());
assertFalse(userThread.isDaemon());
}

6. Заключение

В этом кратком руководстве мы увидели, что такое потоки демона и для чего их можно использовать в нескольких практических сценариях.

Как всегда, полная версия кода доступна на GitHub .