必须确保线程处于NEW状态才能调用start(),否则抛IllegalThreadStateException;需三重守卫:一查getState()==NEW,二用volatile标志防重复启动,三校验外部上下文有效性。

在调用 Thread.start() 之前,必须确保线程对象处于 NEW 状态,否则会抛出 IllegalThreadStateException。JDK 的 Thread.start() 内部已做此检查,但若需在调用前主动防御(例如在并发初始化、状态敏感的调度逻辑中),可结合线程状态 + 对象身份 + 初始化约束做多重守卫。
守卫一:显式检查线程状态是否为 NEW
这是最直接的条件。注意:Thread.getState() 是安全的,即使线程已终止或未启动,也不会抛异常:
- 使用
thread.getState() == Thread.State.NEW判断 - 避免仅靠
thread.isAlive() == false,因为TERMINATED线程也返回false,但不可重启
守卫二:防止重复 start 或误复用已构造对象
线程对象不可重用。即使状态是 NEW,也要防范“被其他代码意外调用过 start()”(比如共享引用、测试误操作):
- 引入私有 volatile 标志(如
private volatile boolean started;),在真正调用start()前原子设为true - 配合
compareAndSet或同步块实现“首次且仅一次”语义,避免竞态下多次进入启动逻辑
守卫三:校验线程所属上下文是否仍有效
某些场景下,“合规 NEW”不仅指状态,还依赖外部约束,例如:
- 线程绑定的资源(如
ExecutorService是否 shutdown) - 业务上下文是否过期(如关联的请求 ID 已失效、任务已取消)
- 可通过自定义字段(如
private final AtomicBoolean contextValid = new AtomicBoolean(true);)配合业务逻辑联合判断
组合示例(简洁可嵌入的守卫方法)
以下是一个轻量、线程安全的守卫工具片段:
public static boolean canStartSafely(Thread t, Supplier<Boolean> contextCheck) {
if (t == null) return false;
if (t.getState() != Thread.State.NEW) return false;
// 防重入(假设你有 started 标志)
if (started.get()) return false;
// 外部上下文校验
return contextCheck.get() != null && contextCheck.get();
}
调用时:务必在 synchronized(t) 或 CAS 更新标志后立即执行 t.start(),避免检查通过后状态突变。

















