【问题标题】:Difference between a daemon thread and a low priority thread守护线程和低优先级线程的区别
【发布时间】:2012-04-24 12:56:55
【问题描述】:

最近有人问我一个问题:

我们有setPriority() 方法来设置线程为低优先级。 那为什么我们需要一个守护线程。它们有什么区别?

将线程标记为守护进程是否会改变其调度?

【问题讨论】:

    标签: java multithreading


    【解决方案1】:

    我们有 setPriority() 方法将线程设置为低优先级。那为什么我们需要一个守护线程。它们有什么区别?

    通常,守护线程与优先级无关。当所有用户非守护线程完成时,JVM 将关闭。将线程标记为守护线程意味着在JVM退出时可以安全地杀死它。

    优先级与调度有关——与其他准备运行的线程相比,一个线程获得时间片的频率。您可以拥有低优先级守护线程或高优先级守护线程。您可以拥有低优先级和高优先级的非守护线程。顺便说一句,线程优先级仅适用于某些特定情况和特定架构,作为 Java 线程专家,我从不使用它们。

    这些概念是正交的(相互独立)——至少在 Java 线程模型中是这样。

    就何时创建​​线程守护进程而言,我将守护线程用于任何我不关心它们是否在 JVM 退出时被中断的任务:保持活动线程、统计处理器、日志处理等。一切对应用程序至关重要的任务是一个非守护线程,必须专门中断或发出信号以以某种方式退出。

    【讨论】:

    • 谢谢格雷。那么创建一个线程(在java中)并使它成为一个守护线程有什么用呢?有没有我们使用它的实际场景?
    • 我将守护线程用于我不在乎在 JVM 退出时是否被中断的任何事情:保持活动线程、统计处理器、日志处理等。对应用程序至关重要的所有任务都是一个非守护进程。
    【解决方案2】:

    正在运行的守护线程不会阻止您的程序结束/退出。但是,所有用户线程必须在您的程序退出之前结束。优先级可能适用于守护进程或用户线程。 priority 的理解方式可能与您在日常生活中的理解方式相同。

    【讨论】:

      【解决方案3】:

      一个例子

      1. JVM 在低优先级线程完成时关闭。尽管守护线程仍在运行
      2. ALSO,表示由守护线程创建的线程自动成为守护线程

        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(); 
            }
        
        }
        

        输出是: 用户线程启动
        守护进程真实 id = 守护进程
        守护进程真实 id = DaemonChild
        守护进程真实 id = 守护进程
        守护进程真实 id = DaemonChild
        守护进程真实 id = 守护进程
        守护进程真实 id = DaemonChild
        守护进程真实 id = 守护进程
        守护进程真实 id = DaemonChild
        用户线程结束(程序退出)
        守护进程真实 id = DaemonChild
        守护进程真 id = 守护进程

      【讨论】:

        【解决方案4】:

        如果 Java 运行时确定应用程序中运行的唯一线程是守护线程(即不存在用户线程),Java 运行时会立即关闭应用程序,从而有效地阻止所有死在其轨道上的守护线程。为了让应用程序继续运行,它必须始终具有至少一个活动用户线程。在所有其他方面,Java 运行时以完全相同的方式处理守护线程和用户线程。

        除了在守护线程中......当 JVM 突然终止时,finally 块不会被执行,堆栈不会被展开——JVM 只是退出。由于这个原因,应该谨慎使用守护线程,将它们用于可能执行任何类型 I/O 的任务是很危险的。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-11-26
          • 2012-08-07
          • 2011-04-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多