【问题标题】:What is a daemon thread in Java?Java中的守护线程是什么?
【发布时间】:2011-01-13 21:00:42
【问题描述】:

谁能告诉我Java中的守护线程是什么?

【问题讨论】:

标签: java multithreading


【解决方案1】:

守护线程是在程序完成但线程仍在运行时不会阻止 JVM 退出的线程。一个守护线程的例子就是垃圾回收。

您可以在线程启动之前使用setDaemon(boolean) 方法更改Thread 守护程序属性。

【讨论】:

  • 为了后代,setDamon(boolean) 只能在线程启动之前调用。默认情况下,线程继承其父线程的守护进程状态。
  • “当程序完成但线程仍在运行时不会阻止 JVM 退出”,而 @sateesh 说“JVM 停止任何剩余的守护程序线程被放弃”。那么当JVM退出时,守护线程是否完成运行?
  • @Gerald, ALL 线程在 JVM 退出时被杀死。 B_erb 说:“……当程序结束时。”这意味着,如果程序没有明确地杀死 JVM,那么当最后一个 non-daemon 线程结束时,JVM 会自动杀死自己。普通线程定义“程序何时退出”。守护线程不会。
  • 所以thread that does not prevent the JVM from exiting when the program finishes but the thread is still running这一行基本上意味着启动线程的JVM进程并不关心守护线程是否完成执行,如果所有正常线程都完成执行,它就会自行结束。
  • @SolomonSlow 在 JVM 结束时杀死仍在工作的守护线程(例如垃圾收集器)会产生什么后果?谢谢。
【解决方案2】:

还有几点(参考:Java Concurrency in Practice

  • 当一个新线程被创建时,它会继承它的守护进程状态 父母。
  • 当所有非守护线程都完成后,JVM 停止,并且所有剩余的守护线程都被放弃

    • finally 块没有被执行
    • 堆栈没有展开 - JVM 刚刚退出。

    由于这个原因,应该谨慎使用守护线程,将它们用于可能执行任何类型 I/O 的任务是很危险的。

【讨论】:

  • 为什么不应该将守护线程用于 I/O?是否担心 BufferedWriters 等没有被刷新?
  • @PaulCager 是的,他们也可以在写入/读取的过程中被膝盖切断。
  • 第二点是废话。当 JVM 停止时,所有 线程都死掉并且没有finally 块被执行,无论线程是否是守护进程。因此,如果您认为可能有正在运行的线程在执行 I/O,请不要调用 System.exit(…)。唯一不同的是,当只剩下守护线程时,JVM会触发自己的终止。
  • “堆栈未展开”是什么意思?
  • @ɢʜʘʂʈʀɛɔʘɴ 有一些关于“展开堆栈”的解释,包括这个:flylib.com/books/en/2.254.1.277/1
【解决方案3】:

以上所有答案都很好。这里有一个简单的小代码sn-p,来说明区别。用setDaemon中的true和false的每一个值试试。

public class DaemonTest {
    
    public static void main(String[] args) {
        new WorkerThread().start();

        try {
            Thread.sleep(7500);
        } catch (InterruptedException e) {
            // handle here exception
        }

        System.out.println("Main Thread ending") ;
    }

}

class WorkerThread extends Thread {
    
    public WorkerThread() {
        // When false, (i.e. when it's a non daemon thread),
        // the WorkerThread continues to run.
        // When true, (i.e. when it's a daemon thread),
        // the WorkerThread terminates when the main 
        // thread or/and user defined thread(non daemon) terminates.
        setDaemon(true); 
    }
    
    public void run() {
        int count = 0;

        while (true) {
            System.out.println("Hello from Worker "+count++);

            try {
                sleep(5000);
            } catch (InterruptedException e) {
                // handle exception here
            }
        }
    }
}

【讨论】:

  • @russ 好代码 sn-p!我不得不将 WorkerThread 类定义为静态的。
  • @xli 你也可以完成 new DaemonTest().new WorkerThread().start() :)
  • @russ 很好的例子。我知道如果您没有明确定义“setDaemon(true)”,默认值是“setDeamon(false)”
  • catch (InterruptException) 块中也有类似 println() 的东西可以清楚地表明守护线程不会通过中断机制退出,它们会突然停止存在。
【解决方案4】:

传统上,UNIX 中的守护进程是那些不断在后台运行的进程,很像 Windows 中的服务。

Java 中的守护线程不会阻止 JVM 退出。具体来说,当只剩下守护线程时,JVM 将退出。您可以通过在Thread 上调用setDaemon() 方法来创建一个。

阅读Daemon threads

【讨论】:

  • 您的链接此时已失效,也许您想更新?无论如何,为你 +1。
  • 我喜欢 UNIX 和 Windows 之间的比较。
  • 最好的解释在这里!
【解决方案5】:

守护线程就像是其他线程或对象的服务提供者,它们与守护线程在同一进程中运行。守护线程用于后台支持任务,仅在正常线程执行时才需要。如果正常线程没有运行并且剩余线程是守护线程,则解释器退出。

例如,HotJava 浏览器使用多达四个名为“Image Fetcher”的守护线程从文件系统或网络中为任何需要一个的线程获取图像。

守护线程通常用于为您的应用程序/小程序执行服务(例如加载“fiddley bits”)。用户线程和守护线程的核心区别在于,JVM 只会在所有用户线程都终止后才会关闭程序。当不再有任何用户线程(包括执行的主线程)在运行时,JVM 会终止守护线程。

setDaemon(true/false) ?该方法用于指定一个线程为守护线程。

public boolean isDaemon() ? 该方法用于判断线程是否为守护线程。

例如:

public class DaemonThread extends Thread {
    public void run() {
        System.out.println("Entering run method");

        try {
            System.out.println("In run Method: currentThread() is" + Thread.currentThread());

            while (true) {
                try {
                    Thread.sleep(500);
                } catch (InterruptedException x) {}

                System.out.println("In run method: woke up again");
            }
        } finally {
            System.out.println("Leaving run Method");
        }
    }
    public static void main(String[] args) {
        System.out.println("Entering main Method");

        DaemonThread t = new DaemonThread();
        t.setDaemon(true);
        t.start();

        try {
            Thread.sleep(3000);
        } catch (InterruptedException x) {}

        System.out.println("Leaving main method");
    }

}

输出:

C:\java\thread>javac DaemonThread.java

C:\java\thread>java DaemonThread
Entering main Method
Entering run method
In run Method: currentThread() isThread[Thread-0,5,main]
In run method: woke up again
In run method: woke up again
In run method: woke up again
In run method: woke up again
In run method: woke up again
In run method: woke up again
Leaving main method

C:\j2se6\thread>

【讨论】:

    【解决方案6】:

    守护进程:d(isk) a(nd) e(xecution) mon(itor) 或来自 de(vice) mon(itor)

    守护进程定义(计算):

    处理后台打印和文件传输等服务请求的后台进程,不需要时处于休眠状态。

    —— 来源:English by Oxford Dictionaries

    什么是 Java 中的守护线程?

    • 守护线程可以在其流程之间的任何时间关闭,非守护线程,即用户线程完全执行。
    • 守护线程是在后台间歇运行的线程,只要其他非守护线程在运行。
    • 当所有非守护线程都完成后,守护线程会自动终止。
    • 守护线程是在同一进程中运行的用户线程的服务提供者。
    • JVM 不关心守护线程在运行状态时是否完成,即使是 finally 块也让执行。 JVM 确实优先考虑我们创建的非守护线程。
    • 守护线程在 Windows 中充当服务。
    • 当所有用户线程(与守护线程相反)终止时,JVM 会停止守护线程。因此,可以使用守护线程来实现例如监控功能,因为一旦所有用户线程停止,JVM 就会停止线程。

    【讨论】:

    • 如果调用 System.exit(),无论线程是守护线程,都不会执行 finally 块。确实 finally 块在守护线程中执行,即使 如果 JVM 还没有杀死线程,最后一个用户线程终止
    • 守护线程以其创建线程相同的优先级执行,除非它在启动之前已被更改。守护线程不一定是“服务提供者”或 Windows 服务或此处所述的任何其他内容:它们只是不会阻止 JVM 退出的线程。期间。
    【解决方案7】:

    守护线程是被认为在后台执行某些任务的线程,例如处理请求或应用程序中可能存在的各种计时作业。

    当您的程序只剩下 守护线程 时,它将退出。这是因为这些线程通常与普通线程一起工作并提供事件的后台处理。

    您可以使用setDaemon 方法指定Thread 是一个守护进程,它们通常不会退出,也不会被中断。它们只是在应用程序停止时停止。

    【讨论】:

    • 因为它是一个守护线程,这就是“守护”的意思。你的推理又回到了前面。
    【解决方案8】:

    我想澄清一个误解:

    • 假设如果守护线程(比如 B)是在用户线程(比如 一种);那么这个用户线程/父线程(A)的结束不会结束 它创建的守护线程/子线程(B);提供的用户线程是唯一的 一个正在运行。
    • 所以线程结束时没有父子关系。一旦没有单个活动用户线程并导致 JVM 终止,所有守护线程(无论它是在哪里创建的)都将结束。
    • 即使这两个(父/子)都是守护线程也是如此。
    • 如果子线程是从守护线程创建的,那么它也是守护线程。这不需要任何显式的守护线程标志设置。 同样,如果从用户线程创建的子线程也是用户线程,如果要更改它,则需要在该子线程启动之前显式设置守护进程标志。

    【讨论】:

    • 本文没有引用任何内容。不要对未引用的文本使用引用格式。 “引用”的第一段不正确,与第二段相矛盾。
    • @EJP 明白了,所以每个人都必须在这里给其他人报价,而不是他们自己的。或者我们自己在某处引用然后指向这里?
    • 是的,如果你引用了某人,你必须引用他们,就像其他任何地方一样,如果你没有引用任何人,请不要像你有那样格式化它。我无法确定你第二句话的开头或结尾。
    【解决方案9】:

    守护线程和用户线程。通常,程序员创建的所有线程都是用户线程(除非您将其指定为守护线程或您的父线程是守护线程)。用户线程通常用于运行我们的程序代码。除非所有用户线程都终止,否则 JVM 不会终止。

    【讨论】:

      【解决方案10】:

      Java 有一种特殊的线程,称为daemon 线程。

      • 非常低的优先级。
      • 仅在同一程序的其他线程没有运行时执行。
      • JVM 结束程序完成这些线程,当守护线程 程序中运行的唯一线程。

      守护线程有什么用?

      通常用作普通线程的服务提供者。 通常有一个无限循环等待服务请求或执行线程的任务。 他们不能做重要的工作。 (因为我们不知道它们什么时候会有 CPU 时间,如果没有其他线程在运行,它们可以随时完成。)

      这类线程的一个典型例子是 Java 垃圾收集器

      还有更多……

      • 您只在调用start() 方法之前调用setDaemon() 方法。线程运行后,您无法修改其守护进程状态。
      • 使用isDaemon()方法检查线程是守护线程还是用户线程。

      【讨论】:

      • -1,我不相信守护线程本质上是低优先级的。当然,我没有看到这样的文档。这个 SO 答案还声称优先级和守护进程是正交的:stackoverflow.com/a/10298353/839128
      • 守护线程与优先级无关。你可以有一个高优先级的守护线程或一个低优先级的非守护线程。
      • 守护线程最初与创建线程具有相同的优先级。
      • 语句“'仅在同一程序的其他线程没有运行时才执行”具有误导性。
      【解决方案11】:

      守护线程就像助手。非守护线程就像是前锋。助手帮助表演者完成工作。工作完成后,表演者不再需要帮助来表演。由于不需要帮助,助手们离开了这个地方。因此,当非守护线程的工作结束时,守护线程就会离开。

      【讨论】:

        【解决方案12】:

        在 Java 中,守护线程是不阻止 Java 虚拟机 (JVM) 退出的线程类型之一。 守护线程的主要目的是执行后台任务,尤其是在一些例行的周期性任务或工作的情况下。随着 JVM 的退出,守护线程也会死掉。

        通过设置thread.setDaemon(true),线程成为守护线程。但是,您只能在线程启动之前设置此值。

        【讨论】:

        • 还有哪些其他类型的线程可以做到这一点?答:没有。有守护线程和非守护线程,句号。它是一个二进制,两种状态。
        【解决方案13】:

        这是一个测试守护线程行为的示例,以防 jvm 由于不存在用户线程而退出。

        请注意下面输出中的倒数第二行,当主线程退出时,守护线程也死了,并且没有在 finally 块中打印 finally executed9 语句。这意味着如果 JVM 由于不存在用户线程而退出,则在守护线程的 finally 块中关闭的任何 i/o 资源都不会被关闭。

        public class DeamonTreadExample {
        
        public static void main(String[] args) throws InterruptedException {
        
            Thread t = new Thread(() -> {
                int count = 0;
                while (true) {
                    count++;
                    try {
                        System.out.println("inside try"+ count);
                        Thread.currentThread().sleep(1000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } finally {
                        System.out.println("finally executed"+ count);
                    }
                }
            });
            t.setDaemon(true);
            t.start();
        
            Thread.currentThread().sleep(10000);
            System.out.println("main thread exited");
          }
        }
        

        输出

        inside try1
        finally executed1
        inside try2
        finally executed2
        inside try3
        finally executed3
        inside try4
        finally executed4
        inside try5
        finally executed5
        inside try6
        finally executed6
        inside try7
        finally executed7
        inside try8
        finally executed8
        inside try9
        finally executed9
        inside try10
        main thread exited
        

        【讨论】:

          【解决方案14】:

          守护线程和普通线程一样,只是JVM只会在其他非守护线程不存在时关闭。守护线程通常用于为您的应用程序执行服务。

          【讨论】:

            【解决方案15】:

            Java 中的守护线程是那些在后台运行的线程,主要由 JVM 创建,用于执行后台任务,如垃圾收集和其他内务管理任务。

            注意事项:

            1. 在 Java 中运行 main 方法的主线程创建的任何线程默认情况下都是非守护进程,因为 Thread 从创建它的线程(即父线程)继承其守护进程特性,并且由于主线程是非守护线程,因此任何从它创建的其他线程将保持非守护进程,直到通过调用 setDaemon(true) 显式创建守护进程。

            2. Thread.setDaemon(true) 创建一个 Thread 守护进程,但它只能在 Java 中启动 Thread 之前调用。如果对应的 Thread 已经启动并运行,则会抛出 IllegalThreadStateException。

            Java中守护线程和非守护线程的区别:

            1) JVM 在存在之前不会等待任何守护线程完成。

            2) 当 JVM 终止时,守护线程与用户线程的处理方式不同,finally 块不会被调用,堆栈不会被解除并且 JVM 只是退出。

            【讨论】:

              【解决方案16】:

              正如大家所解释的,守护线程不会限制 JVM 退出,所以从退出的角度来看,它基本上是应用程序的一个快乐线程。

              想补充一点,当我提供一个 API,比如将数据推送到 3rd 方服务器/或 JMS 时,可以使用守护线程,我可能需要在客户端 JVM 级别聚合数据,然后发送到 JMS单独的线程。如果这不是要推送到服务器的强制性数据,我可以将此线程作为守护线程。 这种数据就像日志推送/聚合。

              问候, 马尼什

              【讨论】:

              【解决方案17】:

              守护线程就像是负责管理资源的守护进程,由Java VM创建一个守护线程来为用户线程服务。 unix 更新系统示例,unix 是守护进程。 守护线程的子线程始终是守护线程,因此默认守护进程为假。您可以使用“isDaemon()”方法检查线程是否为守护线程或用户。 所以守护线程或守护进程基本上负责管理资源。 例如,当您启动 jvm 时,垃圾收集器正在运行,它是优先级为 1 的守护线程,它正在管理内存。 jvm只要用户线程还活着,你就不能杀死守护线程。jvm负责杀死守护线程。

              【讨论】:

              • 非常困惑,所有的'so's都是不合逻辑的。
              【解决方案18】:

              对我来说,守护线程就像是用户线程的管家。 如果所有用户线程都完成了,则守护线程没有工作并且 被JVM杀死。 我在YouTube video里解释过了。

              【讨论】:

                【解决方案19】:

                让我们只讨论带有工作示例的代码。我喜欢上面 russ 的回答,但为了消除我的任何疑问,我对其进行了一些改进。我运行了两次,一次将工作线程设置为 deamon true(deamon 线程),另一次将其设置为 false(用户线程)。当主线程终止时,它确认守护线程结束。

                public class DeamonThreadTest {
                
                public static void main(String[] args) {
                
                    new WorkerThread(false).start();    //set it to true and false and run twice.
                
                    try {
                        Thread.sleep(7500);
                    } catch (InterruptedException e) {
                        // handle here exception
                    }
                
                    System.out.println("Main Thread ending");
                    }
                   }
                
                   class WorkerThread extends Thread {
                
                    boolean isDeamon;
                
                    public WorkerThread(boolean isDeamon) {
                        // When false, (i.e. when it's a user thread),
                        // the Worker thread continues to run.
                        // When true, (i.e. when it's a daemon thread),
                        // the Worker thread terminates when the main
                        // thread terminates.
                        this.isDeamon = isDeamon;
                        setDaemon(isDeamon);
                    }
                
                    public void run() {
                        System.out.println("I am a " + (isDeamon ? "Deamon Thread" : "User Thread (none-deamon)"));
                
                        int counter = 0;
                
                        while (counter < 10) {
                            counter++;
                            System.out.println("\tworking from Worker thread " + counter++);
                
                            try {
                                sleep(5000);
                            } catch (InterruptedException e) {
                                // handle exception here
                            }
                        }
                        System.out.println("\tWorker thread ends. ");
                    }
                }
                
                
                
                result when setDeamon(true)
                =====================================
                I am a Deamon Thread
                    working from Worker thread 0
                    working from Worker thread 1
                Main Thread ending
                
                Process finished with exit code 0
                
                
                result when setDeamon(false)
                =====================================
                I am a User Thread (none-deamon)
                    working from Worker thread 0
                    working from Worker thread 1
                Main Thread ending
                    working from Worker thread 2
                    working from Worker thread 3
                    working from Worker thread 4
                    working from Worker thread 5
                    working from Worker thread 6
                    working from Worker thread 7
                    working from Worker thread 8
                    working from Worker thread 9
                    Worker thread ends. 
                
                Process finished with exit code 0
                

                【讨论】:

                • 你的例子不起作用并且总是返回相同的场景。只显示两次出现。
                【解决方案20】:

                守护线程通常被称为“服务提供者”线程。这些线程不应用于执行程序代码,而应用于执行系统代码。这些线程与您的代码并行运行,但 JVM 可以随时终止它们。当 JVM 找不到用户线程时,它会停止它并且所有守护线程都会立即终止。我们可以使用以下方法将非守护线程设置为守护线程:

                setDaemon(true)
                

                【讨论】:

                • 它们不是“通常称为“服务提供者”的线程”。
                • 它们可以用来执行任何代码。 JVM 不能“随时杀死它们”,但它在没有非守护线程运行时杀死它们。
                • @EJP 也许我错了,但是当非守护线程运行时“它会杀死他们”。当一个线程是守护进程时,它不是单独运行保持jvm直到它完全执行并且现在在操作系统级别进行管理。
                • 它会在所有非守护线程退出时杀死它们,而不是在皮秒之前。当然不是“任何时候”。
                【解决方案21】:

                守护线程是在后台运行的线程,只要进程的其他非守护线程仍在运行。因此,当所有非守护线程完成时,守护线程终止。非守护线程的一个例子是运行 Main 的线程。 在线程启动前调用setDaemon()方法使线程成为守护进程

                更多参考:Daemon thread in Java

                【讨论】:

                  【解决方案22】:

                  已经有很多答案了;但是,也许我可以更清楚地说明这一点,因为当我阅读 Daemon Threads 时,最初,我有一种感觉,我理解得很好;然而,在玩过它并调试了一下之后,我观察到了一个奇怪的(对我来说)行为。

                  我被教导说:

                  如果我希望线程在主线程有序执​​行完后立即死亡,我应该将其设置为 Diamond。

                  我尝试了什么:

                  • 我从Main Thread 创建了两个线程,我只将其中的一个设置为diamond
                  • 在有序完成Main Thread 的执行后,这些新创建的线程都没有退出,但我预计,Daemon 线程应该已经退出;
                  • 我浏览了许多博客和文章,到目前为止,我发现的最好和最清晰的定义来自Java Concurrency In Practice 这本书,其中非常清楚地指出:

                  7.4.2 守护线程

                  有时你想创建一个线程来执行一些帮助程序 函数,但您不希望该线程的存在阻止 JVM 从关闭。这就是守护线程的用途。 线程分为两种类型:普通线程和守护线程。 当 JVM 启动时,它创建的所有线程(如垃圾 收集器和其他管家线程)是守护线程,除了 主线程。创建新线程时,它会继承守护进程 创建它的线程的状态,因此默认情况下任何线程 主线程创建的也是普通线程。普通线程和 守护线程的区别仅在于它们退出时发生的情况。当一个 线程退出,JVM 对正在运行的线程进行清点,如果 剩下的唯一线程是守护线程,它启动一个 有序关机。当 JVM 停止时,所有剩余的守护线程 废弃——finally 块没有被执行,栈没有被展开—— JVM 刚刚退出。应谨慎使用守护线程——很少处理 活动可以随时安全地放弃,无需清理。在 特别是,将守护线程用于可能会导致的任务是很危险的 执行任何类型的 I/O。守护线程最好保存为 “家务”任务,例如定期执行的后台线程 从内存缓存中删除过期条目。

                  【讨论】:

                    【解决方案23】:

                    当最后一个非守护线程执行完成时,JVM 将完成这项工作。默认情况下,JVM 将创建一个线程作为非守护进程,但我们可以借助 setDaemon(true) 方法将线程创建为守护进程。 Daemon 线程的一个很好的例子是 GC 线程,它会在所有非守护线程完成后立即完成他的工作。

                    【讨论】:

                    • GC 线程是如何工作的?即使程序的主线程花费了很长时间(主线程没有终止),垃圾回收也不会运行吗?
                    • 正如我提到的 GC 线程将一直工作到最后一个 NON 守护线程将完成它的执行。程序的主线程不是我们所知道的守护进程,因此一旦主线程完成/终止,GC 线程将完成工作。基本上我想说的是守护线程将在进程完成时终止,并且在执行所有非守护线程时进程完成。
                    • 默认情况下,线程的守护进程状态是从其父级继承的。
                    【解决方案24】:
                    • 守护线程是那些为用户线程提供一般服务的线程(例如:清理服务 - 垃圾收集器)
                    • 守护线程一直在运行,直到被 JVM 杀死
                    • 当 JVM 终止时,守护线程与用户线程的处理方式不同,finally 块不被调用 JVM 只是退出
                    • 除非所有用户线程都终止,否则 JVM 不会终止。如果所有用户线程都死了,JVM 就会终止
                    • JVM 不会等待任何守护线程完成,然后才会调用现有的 finally 块
                    • 如果所有用户线程都死了,JVM 会在停止前杀死所有守护线程
                    • 当所有用户线程都终止后,守护线程也可以终止,主程序也终止
                    • 必须在调用线程的 start() 方法之前调用 setDaemon() 方法
                    • 一旦线程开始执行,其守护进程状态就无法更改
                    • 要确定线程是否为守护线程,请使用访问器方法 isDaemon()

                    【讨论】:

                      【解决方案25】:

                      Java 守护线程

                      [Daemon process]

                      Java 使用 user threaddaemon tread 概念。

                      JVM 流程

                      1. If there are no `user treads` JVM starts terminating the program
                      2. JVM terminates all `daemon threads` automatically without waiting when they are done
                      3. JVM is shutdown
                      

                      如您所见,daemon treaduser treads服务线程

                      • daemon tread 是低优先级线程。
                      • 线程从父线程继承它的属性。要在外部设置它,您可以使用 setDaemon() 方法 before 启动它或通过 isDaemon() 检查它

                      【讨论】:

                        猜你喜欢
                        • 2016-09-22
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2012-12-25
                        相关资源
                        最近更新 更多