调用 setdaemon(true) 必须在 start() 前设置,否则抛 illegalthreadstateexception;守护线程不阻止 jvm 退出,适合后台任务,不能用于关键逻辑,主线程不可设为守护,子线程继承父线程 daemon 状态。

调用 Thread.setDaemon(true) 可以把一个线程标记为守护线程,但**必须在线程启动前设置**,否则会抛出 IllegalThreadStateException。
必须在 start() 之前调用
守护线程的“身份”是在线程对象创建后、首次执行前确定的。JVM 不允许运行中的线程切换类型。
- ✅ 正确写法:
t.setDaemon(true); // 在 start 前
t.start();
- ❌ 错误写法(会报错):
t.start();
t.setDaemon(true); // 抛出 IllegalThreadStateException
守护线程的生命周期由 JVM 自动管理
守护线程不会阻止 JVM 退出。只要所有用户线程结束,JVM 就会终止,无论守护线程是否还在运行。
- 适合做后台支持性工作:日志轮转、监控心跳、资源清理等
- 不适合做关键业务逻辑:比如保存重要数据、等待外部响应、事务提交等
- 示例场景:一个守护线程每秒打印一次“心跳”,但主函数 sleep(3000) 后就结束,JVM 退出,该线程会被强制终止
主线程不是守护线程,但可以被设为守护?
不可以。主线程(main thread)由 JVM 创建,且默认是非守护线程,无法通过 setDaemon(true) 修改。只有自己创建的 Thread 实例才能设置。
- 可以通过
Thread.currentThread().isDaemon()查看当前线程是否为守护线程 - 子线程默认继承父线程的 daemon 状态:如果主线程创建子线程,子线程默认也是非守护;若在守护线程中新建线程,新线程默认也是守护
注意 setDaemon(true) 和守护行为的关系
这个方法只是“标记”,不改变线程调度优先级、不加速/减速执行,也不影响它能否访问共享资源。它的唯一语义是:告诉 JVM —— “这个线程不重要,别等它”。
- 守护线程中抛出未捕获异常,会导致该线程终止,但不会影响 JVM 或其他线程
- 守护线程可以主动调用
System.exit(),但这会直接终结整个 JVM - 没有 API 能把守护线程再变回用户线程










