跳转到内容

线程生命周期

Java 线程状态由 Thread.State 枚举定义:

状态触发条件退出条件
1. NEWnew Thread() 后、start() 前调用 start()
2. RUNNABLEstart() 之后,包含 Ready 和 Runningrun() 结束或进入等待
3. BLOCKED竞争 synchronized 锁失败成功获得锁
4. WAITINGwait() / join() / LockSupport.park()notify() / notifyAll() / unpark()
5. TIMED_WAITINGsleep(n) / wait(n) / join(n)超时或被唤醒
6. TERMINATEDrun() 方法执行完毕或异常退出终态,不可逆
  • NEW → RUNNABLE:调用 start(),JVM 向操作系统申请创建线程;

  • RUNNABLE → BLOCKED:进入 synchronized 块/方法时锁被其他线程持有;

  • RUNNABLE → WAITING:调用 Object.wait()、Thread.join()、LockSupport.park();

  • RUNNABLE → TIMED_WAITING:调用 Thread.sleep(n)、Object.wait(n)、Thread.join(n);

  • WAITING / TIMED_WAITING → RUNNABLE:被唤醒后不是直接运行,而是先重新竞争锁,竞争成功才回到 RUNNABLE;

  • RUNNABLE → TERMINATED:run() 正常返回或抛出未捕获异常。

对比项Thread.sleep(n)Object.wait()
所属类ThreadObject
是否释放锁不释放释放
唤醒方式超时自动醒需要 notify()
使用前提无必须持有对象锁(在 synchronized 块内)
状态TIMED_WAITINGWAITING

join() 让当前线程阻塞,直到目标线程执行完毕。常用于主线程等待子线程结果。

Thread t = new Thread(() -> {
System.out.println("子线程开始");
// 模拟耗时操作
try { Thread.sleep(1000); } catch (InterruptedException e) {}
System.out.println("子线程结束");
});
t.start();
t.join(); // 主线程阻塞,等待 t 执行完毕
System.out.println("主线程继续"); // 保证在子线程结束后才执行

也可以设置超时,超时后不再等待:

t.join(500); // 最多等待 500ms
Thread.currentThread() // 获取当前线程
thread.getName() / setName()
thread.getPriority() / setPriority(1~10) // 优先级,仅建议性
thread.isDaemon() / setDaemon(true) // 守护线程,JVM 退出时不等待
thread.interrupt() // 中断线程(设置中断标志位)
Thread.interrupted() // 检查并清除中断标志(静态方法)
thread.isInterrupted() // 检查中断标志(不清除)
thread.join() // 等待该线程执行完毕
Thread.yield() // 让出 CPU,重新竞争(很少用)
Thread t = new Thread(() -> {
while (true) { /* 后台任务 */ }
});
t.setDaemon(true); // 必须在 start() 之前设置
t.start();
  • JVM 中所有非守护线程结束时,JVM 会直接退出,不等守护线程完成;

  • 典型守护线程:GC 线程、心跳检测线程。

Q:线程和进程的区别?

A:进程是操作系统资源分配的基本单位,有独立的地址空间;线程是 CPU 调度的基本单位,共享进程的堆内存和方法区,但有各自的栈和程序计数器。线程切换开销远小于进程切换。

Q:Java 线程与操作系统线程是什么关系?

A:Java 线程(JDK 21 之前)是 1:1 映射到内核线程(KLT),由 OS 调度。JDK 21 引入虚拟线程,是 M:N 映射,由 JVM 调度,可以创建数百万个。

Q:线程可以重复 start() 吗?

A:不能。线程一旦进入 TERMINATED 状态就无法重启,再次调用 start() 会抛出 IllegalThreadStateException。

Q:sleep() 和 wait() 的区别?

A:sleep() 属于 Thread 类,不释放锁,超时自动醒,无需持有锁;wait() 属于 Object 类,调用时必须持有对象锁,调用后释放锁进入等待,需要 notify() 唤醒。

Q:WAITING 状态的线程被 notify() 后直接变成 RUNNABLE 吗?

A:不是。notify() 只是将线程从等待队列移到锁的竞争队列,线程还需要重新竞争 synchronized 锁,竞争成功才真正回到 RUNNABLE。