调用 thread.setdaemon(true) 可将线程设为守护线程,使其在 jvm 仅剩守护线程时自动终止;必须在 start() 前调用,否则抛出异常;适用于日志轮转等无需保证完成的后台任务,但不执行 finally,不可用于资源清理。
调用 thread.setdaemon(true) 可以将线程标记为守护线程(daemon thread),使其在 jvm 仅剩守护线程运行时自动终止——这正是实现“随主线程退出而销毁”的关键机制。
守护线程的本质行为
守护线程不会阻止 JVM 退出。JVM 的退出条件是:所有非守护(用户)线程都已结束。只要还有任意一个非守护线程在运行(比如 main 线程),JVM 就继续运行;一旦最后一个非守护线程结束,JVM 立即关闭,所有守护线程被强制中断,不执行 finally 块、不等待 run() 完成。
必须在 start() 之前设置
setDaemon(true) 必须在线程启动前调用,否则会抛出 IllegalThreadStateException。这是常见错误点。
- ✅ 正确:
thread.setDaemon(true); thread.start(); - ❌ 错误:
thread.start(); thread.setDaemon(true);
适合后台监控类任务的典型场景
例如日志轮转、心跳上报、资源使用采样等无需保证执行完成的任务:
- 监控线程定期检查内存或连接数,仅需“尽力而为”,不必等它做完才关程序
- 主线程处理完业务逻辑后自然退出,JVM 收尾时守护线程同步消失,无需显式 interrupt 或 join
- 避免因忘记 shutdown 导致进程挂起(对比 ExecutorService 的 shutdownNow 需手动触发)
注意事项与局限性
守护线程不适合需要可靠清理或持久化操作的场景:
- 不会执行
finally块,不能依赖它释放文件句柄、关闭数据库连接等 - 不能用于替代优雅关闭逻辑(如保存未提交数据、发送终止信号)
- 若主线程是唯一非守护线程,它一结束,守护线程立即被杀死,无缓冲时间










