Java中的守护程序线程是什么?


809

有人可以告诉我Java中有哪些守护程序线程吗?


20
Threadjavadoc的描述它们是什么:java.sun.com/javase/6/docs/api/java/lang/Thread.html
skaffman


2
对于守护程序线程,当JVM停止时,将退出所有守护程序线程。由于这个原因,不应经常使用守护程序线程,因为可能不会对其执行清理。例如,任何I / O都不会正常退出并一直进行写入/读取。
msj121

Answers:


631

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

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


210
为了后代,setDamon(boolean)只能在启动线程之前调用它。默认情况下,线程继承其父线程的守护程序状态。
灰色,

1
@sateesh说:“不会阻止JVM在程序完成时退出,而是线程仍在运行”,而@sateesh则说:“ JVM停止了所有剩余的守护程序线程被放弃”。那么,当JVM退出时,守护程序线程是否完成运行?
杰拉尔德

23
@ Gerald,JVM退出时将杀死所有线程。B_erb说:“ ...程序完成时。” 这意味着,如果程序未明确终止JVM,则当最后一个守护进程线程结束时,JVM将自动终止自身。普通线程定义“程序退出时”。守护进程线程没有。
所罗门慢

2
因此,此行thread that does not prevent the JVM from exiting when the program finishes but the thread is still running基本上意味着启动线程的JVM进程并不关心守护程序线程是否完成执行,如果所有正常线程都已完成执行,它将结束自身。
巴尔加夫

1
@SolomonSlow在JVM结束时杀死仍在工作的守护程序线程(例如,垃圾收集器)会有什么后果?谢谢。
Venkat Ramakrishnan

340

还有几点(参考:Java并发实践

  • 创建新线程时,它将继承其父级的守护程序状态。
  • 当所有非守护程序线程完成时,JVM暂停,所有剩余的守护程序线程都被放弃

    • 最后块不执行
    • 堆栈未解开-JVM刚刚退出。

    因此,应谨慎使用守护程序线程,将其用于可能执行任何I / O的任务是危险的。


3
为什么不应该将守护程序线程用于I / O?是否担心不刷新BufferedWriters等?
Paul Cager 2013年

4
@PaulCager是的,他们也可以在写/读过程中屈膝。
Cruncher 2013年

52
第二点是胡说八道。当JVM暂停时,所有线程都会死亡,并且finally无论线程是否是守护程序,都不会执行任何块。因此,System.exit(…)如果您认为可能有正在运行的线程正在执行I / O,请不要调用。唯一的区别是,仅保留守护程序线程时,JVM将触发自己的终止。
Holger 2014年

11
“堆栈未展开”是什么意思?
ɢʜʘʂʈʀɛɔʘɴ

2
@ɢʜʘʂʈʀɛɔʘɴ关于“展开堆栈”有一些解释,其中包括:flylib.com/books/en/2.254.1.277/1
user766353

175

以上所有答案都是好的。这是一个简单的小代码段,以说明区别。尝试使用中的true和false的每个值setDaemon

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 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.
        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
            }
        }
    }
}

2
@russ好的代码段!我不得不将WorkerThread类定义为静态。
xli

@xli您也可以完成新的DaemonTest()。new WorkerThread()。start():)
没想到,2016年

@russ很好的例子。我知道,如果您未明确定义“ setDaemon(true)”,则默认值是“ setDeamon(false)”
huseyin

96

UNIX中的传统守护进程是那些经常在后台运行的进程,就像Windows中的服务一样。

Java中的守护程序线程是一种不会阻止JVM退出的线程。特别是,仅保留后台驻留程序线程时,JVM将退出。您可以通过在setDaemon()上调用方法来创建一个Thread

阅读Daemon线程


3
您的链接此时已消失,也许您想更新?无论如何,为您+1。
Jasonw 2012年

2
我喜欢UNIX和Windows之间的比较。
2015年

最好的解释在这里!
LoveMeow

57

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

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

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

setDaemon(true / false)?此方法用于指定线程是守护程序线程。

公共布尔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>

37

守护程序的定义(计算):

后台进程处理诸如打印假脱机和文件传输之类的服务请求,并且在不需要时处于休眠状态。

-来源:牛津词典提供的英语

Java中的Daemon线程是什么?

  • 守护进程线程可以在其流之间的任何时间关闭,即非守护进程,即用户线程完全执行。
  • 守护程序线程是只要其他非守护程序线程正在运行,它们就会在后台间歇运行的线程。
  • 当所有非守护程序线程完成时,守护程序线程会自动终止。
  • 守护程序线程是在同一进程中运行的用户线程的服务提供程序。
  • JVM不在乎守护程序线程在处于“运行”状态时是否完成,甚至最终阻塞也不允许执行。JVM会优先考虑由我们创建的非守护线程。
  • 守护程序线程在Windows中充当服务。
  • 当所有用户线程(与守护程序线程相反)终止时,JVM停止守护程序线程。因此,当所有用户线程停止时,守护程序线程可用于实现监视功能,因为该线程将由JVM停止。

如果调用System.exit(),则无论线程是守护程序线程如何,都不会执行finally块。的确finally块在守护线程即使被执行的最后一个用户线程终止,如果JVM没有杀死线程尚未
benez

5
守护程序线程的执行与创建线程的优先级相同,除非在启动之前已对其进行了更改。守护程序线程不一定是“服务提供者”或Windows服务,也不是此处所述的任何其他内容:它们只是不会阻止JVM退出的线程。期。
user207421 '17

35

一个守护线程是被认为做了一些任务,这样可以在应用程序中存在处理请求或各种chronjobs后台线程。

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

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


1
这是因为它是一个守护程序线程,这就是“守护程序”的含义。您的推理又回到了前面。
user207421 '17

15

我想澄清一个误解:

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

这没有引用任何东西。不要为未加引号的文本使用引号格式。“引号”的第一段不正确,与第二段矛盾。
user207421

@EJP GOT IT,所以每个人都必须在这里给其他人报价,而不是自己的报价。还是我们自己在某处引用,然后指向此处?
卡纳加维卢·苏古玛'17

是的,如果您引用某人,必须引用他们,就像在其他地方一样,如果您未引用任何人,则请不要将其格式化。我不能说第二句话的开头或结尾。
user207421 '19

12

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


10

Java有一种特殊的线程,称为守护程序线程。

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

守护程序线程有什么用?

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

此类线程的典型示例是Java垃圾收集器

还有更多...

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

8
-1,我不认为守护线程本质上是低优先级的。当然,我所见过的文档都没有这样的陈述。同样,该SO答案也要求优先级和守护进程是正交的:stackoverflow.com/a/10298353/839128
MikeFHay

5
守护进程线程与优先级无关。您可以具有高优先级的守护程序线程或低优先级的非守护程序线程。
灰色

守护程序线程最初与创建线程具有相同的优先级。
user207421 '17

语句“仅在没有运行同一程序的其他线程时才执行”的说法具有误导性。
Fredrick Gauss

9

守护程序线程就像助手。非守护程序线程就像领先者。助手帮助表演者完成工作。作业完成后,表演者不再需要帮助即可表演。由于不需要帮助,助手便离开了该地点。因此,当非守护程序线程的作业结束时,守护程序线程将前进。


5

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


5

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

注意事项:

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

  2. Thread.setDaemon(true)创建一个Thread守护程序,但是只能在以Java启动Thread之前调用它。如果相应的线程已经启动并且正在运行,它将抛出IllegalThreadStateException。

Java中Daemon和Non Daemon线程之间的区别:

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

2)当JVM终止时,守护进程线程与用户线程的处理方式有所不同,最终不会调用块,不会取消堆栈堆栈,而只是退出JVM。


5

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

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


还有哪些其他类型的线程呢?答:没有。有守护程序线程和非守护程序线程,句点。它是一个二进制的两种状态。
user207421 '17

5

这是一个示例,用于在由于用户线程不存在而导致jvm退出的情况下测试守护程序线程的行为。

请注意下面输出中的倒数第二行,当主线程退出时,守护线程也死了,并且在finally块中没有打印finally execute9语句。这意味着,如果由于用户线程不存在而导致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

4

守护进程线程是众所周知的,不会限制JVM退出,因此从退出的角度来看,它基本上是Application的一个快乐线程。

想要补充一点,当我提供一个API(例如将数据推送到第三方服务器/或JMS)时,可以使用守护程序线程,我可能需要在客户端JVM级别聚合数据,然后在单独的线程中将其发送到JMS。如果这不是要推送到服务器的必需数据,则可以将该线程作为守护程序线程。这种数据就像日志推送/聚合。

问候,Manish


这是一个简单的程序,显示了Java中的守护程序线程。journaldev.com/1072/java-daemon-thread-example
Pankaj

4

守护线程就像守护进程一样,负责管理资源,Java VM创建了一个守护线程来服务用户线程。Unix,unix的示例更新系统是守护进程。守护程序线程的子代始终是守护程序线程,因此默认情况下,守护程序为false。您可以使用“ isDaemon()”方法以守护程序或用户身份检查线程。因此,守护程序线程或守护程序进程基本上负责管理资源。例如,当您启动jvm时,正在运行的垃圾回收器是守护进程线程,其优先级最低为1,即管理内存。只要用户线程处于活动状态,jvm仍处于活动状态,您将无法杀死守护程序线程。jvm负责杀死守护程序线程。


非常困惑,所有的“ so”都不是必需品。
user207421

3

让我们仅以代码和工作示例进行讨论。我喜欢上面的russ的回答,但是为了消除我的任何疑问,我对此做了一些改进。我运行了两次,一次将工作线程设置为deamon true(守护线程),另一次将其设置为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

3

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

setDaemon(true)

3
它们不是“通常称为“服务提供者”线程”。
user207421

1
它们可以用来执行任何代码。JVM不能“随时杀死它们”,但是当没有非守护线程运行时,它将杀死它们。
user207421 '17

@EJP也许我错了,但是当非守护程序线程运行时,“它将杀死它们”。当线程是守护程序时,它不会单独持有jvm来运行,直到它完全执行并现在在OS级别进行管理。
89n3ur0n

当所有非守护进程线程都退出(而不是皮秒之前)时,它将杀死它们。当然不是“任何时候”。
user207421 '19

3

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

有关更多参考:Java中的守护程序线程



2

当最后一个非守护线程执行完成时,JVM将完成工作。默认情况下,JVM将创建一个线程作为非守护进程,但是我们可以在method的帮助下将Thread设置为守护进程setDaemon(true)。守护程序线程的一个很好的例子是GC线程,一旦所有非守护程序线程都完成,它将立即完成他的工作。


GC线程如何工作?即使程序的主线程花费很长时间(主线程不会终止),垃圾回收程序也不会运行吗?
Calicoder '18

正如我提到的那样,GC线程将一直工作到最后一个NON守护程序线程的结尾将完成其执行。程序的主线程不是我们所知道的守护程序,因此一旦主线程完成/被杀死,GC线程将完成工作。基本上,我想说的是,守护进程线程将在进程完成时终止,而在所有非守护进程线程都执行时进程也将完成。
阿曼·图曼扬

默认情况下,线程的守护程序状态是从其父级继承的。
user207421 '19

-1

创建者线程退出时,守护程序线程死亡。

非守护程序线程(默认)甚至可以比主线程寿命更长。

if ( threadShouldDieOnApplicationEnd ) {
    thread.setDaemon ( true );
}
thread.start();

错了 这与创建者线程无关。如果有任何非用户线程在运行,则守护程序线程将继续运行。通过创建产生守护程序线程的前台线程可以很容易地进行测试。即使在前台线程执行join完之后,只要主线程运行,守护进程就会保留很长时间。
休伯特·格热斯科维亚克

当JVM不再是可运行的非守护程序线程时,守护程序线程将死亡。请参阅Javadoc。答案是完全错误的。
user207421 '19
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.