为什么线程启动后不能调用setDaemon(true)方法?
异常抛出的根本原因
该异常是Java线程类的内置约束直接触发的,JDK中Thread.setDaemon()的源码逻辑如下:
public final void setDaemon(boolean on) { checkAccess(); // 核心校验:线程存活(已经启动)则直接抛出异常 if (isAlive()) { throw new IllegalThreadStateException(); } daemon = on; }
线程的守护/用户属性是线程的基础运行属性,必须在启动前确定,一旦调用start()方法后线程进入存活状态,JVM已经将该线程的属性提交给调度系统,中途修改会导致调度逻辑冲突,因此Java从语法层面直接禁止了运行中线程修改守护属性的操作。
你给出的示例代码中先执行了t1.start(),此时t1已经处于存活状态,后续调用setDaemon(true)就会触发该异常。
setDaemon方法的正确使用规则
- 必须在调用
start()启动线程之前调用setDaemon()设置守护属性,线程启动后不允许修改该属性 - 守护线程创建的子线程默认也是守护线程,如果需要子线程为用户线程,必须在子线程启动前手动调用
setDaemon(false)调整 - JVM进程会在所有用户线程全部退出后自动终止,不会等待守护线程的任务执行完成,因此不要在守护线程中处理需要保证完整性的业务逻辑(比如持久化数据写入、事务提交等)
- 守护线程的优先级默认继承自创建它的父线程,如果有特殊调度需求,同样需要在
start()调用前完成优先级配置
内容的提问来源于stack exchange,提问作者javaway
相关产品推荐
相关产品推荐

