9

最近有人问我一个问题:

我们已经有了将setPriority()线程设置为低优先级的方法。那为什么我们需要一个守护线程。他们之间有什么区别?

将线程标记为守护进程会改变它的调度吗?

4

4 回答 4

29

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

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

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

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

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

于 2012-04-24T12:59:08.247 回答
1

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

于 2012-04-24T14:22:26.853 回答
1

一个例子

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

    输出为: User thread 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
    User thread end (程序退出)
    Daemon true id = DaemonChild
    Daemon true id = Daemon

于 2017-06-27T07:27:56.177 回答
0

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

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

于 2015-08-24T13:25:53.937 回答