ChatGPT解决这个技术问题 Extra ChatGPT

Java中的守护线程是什么?

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

Thread javadoc 描述了它们是什么:java.sun.com/javase/6/docs/api/java/lang/Thread.html
对于守护线程,当 JVM 停止时,所有守护线程都将退出由于这个原因,不应该经常使用守护线程,因为可能不会在它们上执行清理。例如,任何 I/O 都不会优雅地退出并一直写入/读取到最后。

G
Gray

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

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


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

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

创建新线程时,它会继承其父线程的守护进程状态。

当所有非守护线程完成时,JVM 停止,所有剩余的守护线程都被放弃:finally 块不执行,堆栈不展开——JVM 只是退出。由于这个原因,应该谨慎使用守护线程,并且将它们用于可能执行任何类型 I/O 的任务是很危险的。

finally 块不被执行,

堆栈没有展开 - JVM 只是退出。


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

以上所有答案都很好。这是一个简单的小代码片段,以说明差异。尝试使用 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 好代码片段!我不得不将 WorkerThread 类定义为静态的。
@xli 你也可以完成 new DaemonTest().new WorkerThread().start() :)
@russ 很好的例子。我知道如果您没有明确定义“setDaemon(true)”,默认值是“setDeamon(false)”
catch (InterruptException) 块中也有类似 println() 的东西可以清楚地表明守护线程不会通过中断机制退出,它们会突然停止存在。
a
aioobe

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

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

阅读Daemon threads


您的链接此时已失效,也许您想更新?无论如何,为你+1。
我喜欢 UNIX 和 Windows 之间的比较。
最好的解释在这里!
N
Nikhil Agrawal

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

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

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

设置守护进程(真/假)?该方法用于指定一个线程是守护线程。

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

P
Premraj

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

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

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

—— 来源:English by Oxford Dictionaries

Java中的守护线程是什么?

守护线程可以在其流程之间的任何时间关闭,非守护线程,即用户线程完全执行。

守护线程是在后台间歇运行的线程,只要其他非守护线程正在运行。

当所有非守护线程完成时,守护线程会自动终止。

守护线程是在同一进程中运行的用户线程的服务提供者。

JVM不关心守护线程在运行状态时完成,即使finally阻塞也让执行。 JVM 确实优先考虑我们创建的非守护线程。

守护线程在 Windows 中充当服务。

当所有用户线程(与守护线程相反)终止时,JVM 会停止守护线程。因此,守护线程可用于实现例如监视功能,因为一旦所有用户线程停止,JVM 就会停止线程。


如果您调用 System.exit(),则不会执行 finally 块,无论线程是守护线程。如果 JVM 尚未终止线程,即使在最后一个用户线程终止后,finally 块也会在守护线程中执行
守护线程以其创建线程相同的优先级执行,除非它在启动之前已被更改。守护线程不一定是“服务提供者”或 Windows 服务或此处所述的任何其他内容:它们只是不会阻止 JVM 退出的线程。时期。
A
ArifMustafa

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

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

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


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

我想澄清一个误解:

假设如果在用户线程(比如 A)中创建了守护线程(比如 B);那么这个用户线程/父线程(A)的结束不会结束它创建的守护线程/子线程(B);提供的用户线程是当前运行的唯一一个。

所以线程结束时没有父子关系。一旦没有单个活动用户线程并导致 JVM 终止,所有守护线程(无论它是在哪里创建的)都将结束。

即使这对于两个(父/子)都是守护线程也是如此。

如果从守护线程创建子线程,那么它也是守护线程。这不需要任何显式的守护线程标志设置。同样,如果从用户线程创建的子线程也是用户线程,如果要更改它,则需要在该子线程启动之前显式设置守护进程标志。


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

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


c
coderatchet

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

非常低的优先级。

仅在同一程序的其他线程没有运行时执行。

当守护线程是程序中运行的唯一线程时,JVM 结束程序完成这些线程。

守护线程是做什么用的?

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

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

还有更多...

您只在调用 start() 方法之前调用 setDaemon() 方法。一旦线程运行,您就不能修改它的守护进程状态。

使用 isDaemon() 方法检查线程是守护线程还是用户线程。


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

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


K
Koray Tugay

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

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


还有哪些其他类型的线程可以做到这一点?答:没有。有守护线程和非守护线程,句号。它是二进制的,两种状态。
B
Bharat Sharma

这是一个在 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

C
Chanikag

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


A
Aniket Thakur

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

注意事项:

由主线程创建的任何在 Java 中运行 main 方法的线程默认都是非守护进程,因为线程从创建它的线程(即父线程)继承其守护进程性质,并且由于主线程是非守护线程,因此从它创建的任何其他线程都会在通过调用 setDaemon(true) 显式创建守护进程之前保持非守护进程。 Thread.setDaemon(true) 创建一个 Thread 守护进程,但它只能在 Java 中启动 Thread 之前调用。如果相应的线程已经启动并运行,它将抛出 IllegalThreadStateException。

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

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

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


M
Manish Malhotra

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

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

问候, 马尼什


这是一个在java中显示守护线程的简单程序。 journaldev.com/1072/java-daemon-thread-example
B
Bosco

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


非常困惑,所有的'so's都是不合逻辑的。
G
Gregory Nozik

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


T
Tony

让我们只讨论带有工作示例的代码。我喜欢上面 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

你的例子不起作用,总是返回相同的场景。只显示两个事件。
P
Pankti

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

setDaemon(true)

它们不是“通常称为“服务提供者”线程”。
它们可用于执行任何代码。 JVM 不能“随时杀死它们”,但它会在没有非守护线程运行时杀死它们。
@EJP 也许我错了,但是当非守护线程运行时“它会杀死它们”。当一个线程是守护进程时,它不是单独运行保持 jvm 直到它完全执行并且现在在 OS 级别进行管理。
当所有非守护线程都退出时,它将杀死它们,而不是之前的皮秒。当然不是“任何时候”。
n
nyi

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

如需更多参考:Daemon thread in Java


G
Giorgi Tsiklauri

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

我被教导说:

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

我尝试了什么:

我从主线程创建了两个线程,我只将其中一个设置为菱形;

在有序地完成主线程的执行后,那些新创建的线程都没有退出,但我预计,那个守护线程应该已经退出了;

我浏览了许多博客和文章,到目前为止我发现的最好和最清晰的定义来自 Java Concurrency In Practice 一书,它非常清楚地指出:

7.4.2 守护线程

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


A
Arman Tumanyan

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


GC线程如何工作?即使程序的主线程花费了很长时间(主线程没有终止),垃圾回收也不会运行吗?
正如我提到的,GC 线程将一直工作到最后一个 NON 守护线程将完成它的执行。正如我们所知,程序的主线程不是守护进程,因此一旦主线程完成/终止,GC 线程将完成工作。基本上我想说守护线程将在进程完成时终止,并且在执行所有非守护线程时进程完成。
默认情况下,线程的守护进程状态是从其父级继承的。
M
Malith Ileperuma

守护线程是那些为用户线程提供一般服务的线程(例如:清理服务 - 垃圾收集器)

守护线程一直在运行,直到被 JVM 杀死

当 JVM 终止时,守护进程线程的处理方式与用户线程不同,finally 块不被调用 JVM 只是退出

除非所有用户线程都终止,否则 JVM 不会终止。如果所有用户线程都死了,JVM 就会终止

JVM 不会等待任何守护线程在存在之前完成,并且 finally 块不会被调用

如果所有用户线程都死了,JVM 在停止之前杀死所有守护线程

当所有用户线程都终止后,daemon线程也可以终止,主程序终止

必须在调用线程的 start() 方法之前调用 setDaemon() 方法

一旦一个线程开始执行它的守护进程状态就不能改变

要确定一个线程是否是守护线程,请使用访问器方法 isDaemon()


y
yoAlex5

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服务线程

守护进程是低优先级线程。

线程从父线程继承它的属性。要在外部设置它,您可以在启动它之前使用 setDaemon() 方法或通过 isDaemon() 检查它