Разница между потоком демона и потоком с низким приоритетом

Недавно мне задали вопрос:

У нас есть метод setPriority() для установки потока для низкого приоритета. Тогда зачем нам нужен поток демона. Какая разница между ними?

Отмечает ли какой-либо поток как демона его планирование?

Ответ 1

У нас есть метод setPriority(), чтобы установить поток для низкого приоритета. Тогда зачем нам нужен поток демона. Какая разница между ними?

Как правило, потоки демона не имеют ничего общего с приоритетом. Например, в Java JVM отключается, когда все пользовательские потоки не-daemon завершаются. Пометить поток как поток демона означает, что его можно безопасно убить, когда JVM завершает работу.

Приоритет - это планирование - о том, как часто поток получает временной срез по сравнению с другими потоками, которые готовы к запуску. У вас могут быть потоки daemon с низким приоритетом или потоки нитей с высоким приоритетом. У вас могут быть потоки не-демона, которые также имеют низкий и высокий приоритет.

Понятия ортогональны (взаимно независимы) - по крайней мере, в модели потока Java.

С точки зрения создания демона потока я использую потоки демона для любых задач, которые меня не волнуют, если они прерываются при выходе из JVM: keep-alive threads, статистические процессоры, обработка журналов и т.д. Все критически важной для приложения является не-демонный поток, который должен быть специально прерван или сигнализирован как-то выйти.

Ответ 2

Выполненный поток демона не помешает вашей программе заканчиваться/выходить. Тем не менее, все пользовательские потоки должны заканчиваться до выхода вашей программы. Приоритет может применяться как к демону, так и к пользовательскому потоку. Вы можете понимать priority так же, как вы понимаете это в повседневной жизни.

Ответ 3

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

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

Ответ 4

Пример

  • Закрытие JVM при завершении нисходящей нити. Несмотря на то, что потоки Daemon все еще запущены
  • ТАКЖЕ, показывает, что поток, созданный потоком демона, автоматически становится потоком демона

    package junk.daemon_thread_example;
    
    class DeamonThreadPlus implements Runnable{
        String id;
        boolean createChild;
    
        public DeamonThreadPlus(String id, boolean createChild){
            this.id = id;
            this.createChild = createChild;
        }
    
        @Override
        public void run() {
            // Parent daemon thread creates child daemon thread by default
            if (createChild)
                new Thread(new DeamonThreadPlus("DaemonChild", false)).start();
    
            // This thread never self-completes (only terminates when process dies)
            while (true){
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Daemon " 
                        + Thread.currentThread().isDaemon()
                        + " id = " + id);
                }
        }
    }
    
    class UThread implements Runnable{
    
        @Override
        public void run() {
            System.out.println("User thread start");
            try {
                Thread.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("User thread end (program exits)");
        }
    }
    
    public class Caller{
    
        public static void main(String[] args) {
            Thread dt = new Thread( new DeamonThreadPlus("Daemon", true));
            dt.setDaemon(true);
            dt.start();
    
            Thread ut = new Thread(new UThread());
            ut.setPriority(Thread.MIN_PRIORITY);
            ut.start(); 
        }
    
    }
    

    Выход: Начало пользовательского потока Daemon true id = Daemon
    Daemon true id = DaemonChild
    Daemon true id = Daemon
    Daemon true id = DaemonChild
    Daemon true id = Daemon
    Daemon true id = DaemonChild
    Daemon true id = Daemon
    Daemon true id = DaemonChild
    Конечный пользовательский поток (завершение программы)
    Daemon true id = DaemonChild
    Daemon true id = Daemon