# java中什么是守护线程?
# 面试回答话术
守护线程专门是为用户提供一种服务的一种线程。它的声明周期是依赖用户线程的。只有jvm仍然存在用户线程正在运行的情况下守护线程有存在的一个意义。
否则jvm进程一但结束了,那么守护线程也会随之结束。
也就是说守护线程不会阻止jvm的一个退出。但是用户线程会。
守护线程和用户线程创建方式其实完全一样的。我们只需要去调用用户线程里面的一个setDaemon()去设置成true就好了。这就表示这个线程是守护线程。而基于守护线程这样的一个特性适合后台通用型服务的一些场景里面。如:
- jvm里面的垃圾回收。是一个典型的使用场景。
这个场景的特殊点:当jvm的进程结束的时候内存的回收线程本身就没有存在的意义了。所以不能因为正在有线程进行垃圾回收导致jvm进程无法结束这个样的一个问题。
基于守护线程的特性,所以不能用在如下场景里面:
- 线程池。
- io的一些任务场景。
因为一但jvm退出以后守护线程也会直接退出。那么就会导致任务还没有执行完或者资源还没有正确释放的一些问题。
一但jvm进程结束后,守护线程也会退出。
守护线程核心特点总结
- 生命周期依赖:守护线程的生命周期完全依赖于用户线程
- 不阻止JVM退出:当所有用户线程结束时,JVM会立即退出,无视守护线程是否仍在运行
- 自动终止:JVM退出时,守护线程会被强制终止,不会执行完线程内的所有代码
记住核心原则:守护线程是为用户线程服务的,不能承担需要可靠执行的任务。在实际开发中,大部分业务场景都应该使用用户线程。
# 创建与设置
- 默认类型:线程默认都是用户线程(非守护线程)
- 设置方法:
Thread thread = new Thread(task);
thread.setDaemon(true); // 必须在start()之前调用
thread.start();
1
2
3
2
3
- 时机要求:必须在调用
start()方法前设置setDaemon(true),否则会抛出IllegalThreadStateException
# 适用应用场景
- JVM内部服务:垃圾回收(GC)线程是典型的守护线程
- 后台监控任务:心跳检测、定期日志清理等
- 辅助性服务:不需要保证完整执行的任务
- 内存清理:缓存清理、临时文件删除等后台任务
# 不适用场景(重要)
- 线程池任务:可能导致任务未完成就被终止
- IO操作:文件写入、数据库操作等需要保证完成的任务
- 资源释放:连接关闭、事务提交等关键操作
- 重要业务逻辑:订单处理、支付确认等必须完成的业务
# 实用建议
- 谨慎使用:除非确定任务可以被安全中断,否则优先使用用户线程
- 资源清理:守护线程中不要执行需要资源清理的操作
- 状态不可靠:不要依赖守护线程的执行结果或状态
- 测试验证:在开发环境中充分测试守护线程的行为
public class Test01 {
public static void main(String[] args) {
// 用户线程示例
Thread userThread = new Thread(() -> {
System.out.println("用户线程运行中...");
});
userThread.start(); // 默认就是用户线程
// 守护线程示例
Thread daemonThread = new Thread(() -> {
while (true) {
System.out.println("守护线程后台运行...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
daemonThread.setDaemon(true); // 设置为守护线程
daemonThread.start();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
main线程不会等待daemonThread执行完毕后在结束。而是直接结束。影响:daemonThread里面代码逻辑的执行。
用户线程运行中...
守护线程后台运行...
Process finished with exit code 0
1
2
3
4
2
3
4
如果需要等待线程完成,就不要把它设置为守护线程。守护线程只适合那些"可有可无、随时可以中断"的后台任务。
重要结论
- 守护线程不应该被等待:如果你需要等待一个线程完成,那么这个线程应该是用户线程
- 设计上的矛盾:守护线程的核心设计目的就是"不需要等待完成",所以"等待守护线程完成"在概念上是矛盾的
- 正确选择:
- 如果任务必须完成 → 使用用户线程
- 如果任务可以中断 → 使用守护线程