Демонические потоки в Java

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

1. Введение

Потоки демонов — это низкоприоритетные потоки, которые будут выполняться в фоновом режиме для обеспечения поддержки потоков, не являющихся демонами(поток, который выполняет основную логику проекта, называется потоком, не являющимся демоном, или пользовательским потоком). Потоки демонов в Java также известны как потоки поставщика услуг.

Давайте рассмотрим ситуацию, когда основной поток работает с малым объемом памяти; тогда JVM запустит сборщик мусора(GC), чтобы уничтожить недоступные объекты, чтобы освободить память, и с этой свободной памятью основной поток сможет продолжить свое выполнение. Так что здесь этот GC является потоком-демоном, который предоставляет услугу очистки памяти для основного потока, чтобы основной поток мог продолжить свое выполнение без каких-либо прерываний. Следовательно, основная цель потоков-демонов — предоставлять услуги основным/пользовательским потокам.

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

Давайте обсудим некоторые важные свойства потоков-демонов:

  • Жизненный цикл потоков-демонов зависит от пользовательских потоков. Он предоставляет услуги пользовательским потокам для фоновых вспомогательных задач.
  • Они не могут предотвратить завершение работы JVM после завершения выполнения всех пользовательских потоков.
  • Когда все пользовательские потоки завершаются, JVM автоматически завершает потоки Daemon.
  • Это поток с максимально низким приоритетом.
  • JVM не будет беспокоиться о том, активен ли поток Daemon или нет.

2. Методы для демонического потока

Следующие методы напрямую создают или проверяют поток на предмет того, является ли он потоком-демоном.

  • void setDaemon(boolean status): Чтобы сделать поток потоком-демоном. Мы можем изменить природу потока, используя этот метод.
  • boolean isDaemon(): Используется для определения, является ли текущий поток демоном. Если поток является демоном, он возвращает true; в противном случае false.

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

public class Task extends Thread{String threadName;public Task(String name){threadName = name;}public void run() {if(Thread.currentThread().isDaemon()){System.out.println(threadName + " is Daemon Thread");} else{System.out.println(threadName + " is User Thread");}}public static void main(String[] args){Task thread1 = new Task("thread1");Task thread2 = new Task("thread2");// Making thread1 as Daemonthread1.setDaemon(true);thread1.start();thread2.start();}}
thread1 is Daemon Threadthread2 is User Thread

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

Task thread = new Task("user-thread");thread.start();thread.setDaemon(true); // java.lang.IllegalThreadStateException

3. Основная тема

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

Поскольку основной поток не является потоком-демоном, любой другой поток, созданный из него, останется недемоном до тех пор, пока он явно не станет демоном, вызвав метод setDaemon(true).

Невозможно изменить природу демона основного потока, поскольку основной поток уже запущен JVM в начале. Если мы попытаемся изменить природу демона основного потока с помощью метода setDaemon(), то это вызовет исключение IllegalThreadStateException.

class ThreadDemo {public static void main(String[] args){System.out.println(Thread.currentThread().isDaemon()); // falseThread.currentThread().setDaemon(true); // java.lang.IllegalThreadStateException}}

4. Завершение потока демона

JVM завершает все потоки демонов независимо от того, запущены ли потоки демонов или нет, когда завершается последний пользовательский поток. Основная цель потока демонов — предоставлять услуги пользовательскому потоку для фоновых задач поддержки. Если пользовательского потока нет, почему JVM должна продолжать запускать этот поток демонов? Вот почему JVM завершает поток демонов, если пользовательского потока нет.

class Task extends Thread {public void run(){for(int i=0;i<10;i++){System.out.println("Child Thread is executing");try {Thread.sleep(2000);} catch(InterruptedException e){//...}}}}class ThreadDemo{public static void main(String[] args){Task thread = new Task();thread.setDaemon(true);thread.start();System.out.println("Main thread is terminating");}}

Обратите внимание на вывод. Когда основной/пользовательский поток завершается, немедленно завершается и поток-демон, т.е. дочерний поток, и он не завершится. Это цикл for 10 раз, и JVM завершает его в середине.

Child Thread is executingmain thread is terminating

5. Когда использовать потоки демонов?

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

Мы можем использовать Daemon Threads в таких случаях:

  • Сбор статистики и выполнение задач мониторинга состояния — отправка и получение сетевых тактовых импульсов, предоставление услуг инструментам мониторинга и т. д.
  • Выполнение асинхронных задач ввода-вывода. Мы можем создать очередь запросов ввода-вывода и настроить группу потоков-демонов, обслуживающих эти запросы асинхронно.
  • Прослушивание входящих соединений — потоки-демоны очень удобны в таких ситуациях, поскольку они позволяют нам программировать простой «вечный» цикл вместо создания настройки, которая обращает внимание на запросы на выход из основного потока.

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

Давайте теперь рассмотрим некоторые различия между потоками-демонами и потоками, не являющимися демонами:

  • Создание: JVM создает потоки демонов, тогда как приложение создает свои собственные пользовательские потоки.
  • Использование: Потоки-демоны обслуживают пользовательские потоки и всегда работают в фоновом режиме, тогда как пользовательские потоки используются для приоритетных задач и задач ввода-вывода приложения.
  • Приоритет: потоки демонов имеют низкий приоритет, тогда как пользовательские потоки имеют высокий приоритет.
  • Поведение JVM: JVM не ждет завершения выполнения потоков-демонов, тогда как JVM ждет завершения выполнения пользовательского потока.
  • Жизненный цикл: жизненный цикл потоков-демонов зависит от пользовательских потоков, тогда как пользовательские потоки имеют независимый жизненный цикл.
  • Завершение: все потоки демонов завершаются после завершения последнего пользовательского потока, независимо от положения потока демонов в этот момент, тогда как пользовательские потоки завершаются после завершения соответствующих им заданий.

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

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

Прокрутить вверх