守护线程(Daemon Threads)详解:与非守护线程的区别
- 1、守护线程是什么?
- 2、守护线程与非守护线程的区别
- 2.1 JVM关闭行为
- 2.2 任务性质
- 2.3 线程设置
- 2.4 示例代码
- 3、总结
💖The Begin💖点点关注,收藏不迷路💖
|
线程被明确区分为守护线程(Daemon Threads)和非守护线程(User Threads 或 Non-Daemon Threads)。它们在JVM中的行为,特别是在JVM关闭时的表现上,存在显著差异。
1、守护线程是什么?
守护线程是一种特殊类型的线程,它们服务于用户线程(非守护线程)。主要特点是:当JVM中没有任何非守护线程运行时,JVM将直接退出,而不会等待守护线程完成其执行。这种设计使得守护线程成为执行如垃圾收集(GC)、JVM内部监控等后台任务的理想选择。
2、守护线程与非守护线程的区别
2.1 JVM关闭行为
- 非守护线程:当所有非守护线程都终止时,JVM才会退出。若存在非守护线程仍在运行,JVM将等待它们完成。
- 守护线程:JVM不会等待守护线程完成。只要没有非守护线程在运行,JVM将立即退出。
2.2 任务性质
- 非守护线程:通常用于执行需要结果或完成某些关键任务的代码,如处理用户请求、执行计算任务等。
- 守护线程:专注于执行后台任务,这些任务在JVM退出前无需完成,如垃圾收集、线程状态监控等。
2.3 线程设置
- 在Java中,通过调用线程对象的
setDaemon(true)
方法,可以将线程设置为守护线程。但这一调用必须在线程启动之前完成。 - 默认情况下,新创建的线程都是非守护线程。
2.4 示例代码
下面是一个简单的示例,展示了如何创建守护线程和非守护线程,并观察它们在JVM关闭时的行为差异。
public class DaemonThreadExample {
public static void main(String[] args) {
// 创建并启动非守护线程
Thread nonDaemonThread = new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println("非守护线程运行中: " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
nonDaemonThread.start();
// 创建并启动守护线程
Thread daemonThread = new Thread(() -> {
for (int i = 0; i < 10; i++) {
System.out.println("守护线程运行中: " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
daemonThread.setDaemon(true); // 设置为守护线程
daemonThread.start();
// 主线程(非守护线程)结束,但非守护线程仍在运行
// 由于主线程是非守护线程,JVM会等待它完成
// 但由于我们没有显式等待非守护线程,它会很快结束
// 实际上,在这个例子中,我们看不到守护线程完成所有迭代,因为JVM会很快退出
}
}
3、总结
它们的主要区别在于JVM关闭时的行为:
1、非守护线程:JVM会等待所有非守护线程完成后才关闭。这些线程通常用于执行关键任务,如用户请求处理。
2、守护线程:JVM关闭时不会等待守护线程完成。守护线程常用于执行后台任务,如垃圾收集,其执行不需要在JVM退出前完成。
创建守护线程很简单,只需在线程启动前调用setDaemon(true)方法。默认情况下,新创建的线程都是非守护线程。
💖The End💖点点关注,收藏不迷路💖
|