join是怎么实现的
1.join() 方法被 synchronized 修饰,意味着当前线程调用 t.join() 时,必须先获取目标线程 t 的对象锁(即进入 t 的同步代码块)。
2.方法内部通过 while (isAlive()) 循环检查目标线程是否存活:
-若存活,当前线程调用 wait(0)(在目标线程 t 上等待),释放 t 的对象锁并进入阻塞状态。
-若已终止,循环退出,join() 方法返回,当前线程继续执行。
3.当目标线程 t 执行完毕(终止)时,JVM 会自动调用 t 的 notifyAll() 方法,唤醒所有等待在 t 上的线程(包括调用 t.join() 的当前线程)。
join() 是 synchronized、wait()、notifyAll() 协同工作的典型案例,其线程同步能力完全依赖 Java 内置锁和对象等待机制。
Thread.sleep()线程的状态
Thread.sleep() 会改变线程状态,它会将线程从 运行状态(Running) 转换为 限时等待状态(TIMED_WAITING),并在指定时间后(或被中断时)恢复为 就绪状态(Runnable)。
Java 的线程状态是 JVM 对线程行为的逻辑抽象,其底层依赖操作系统的线程状态实现。TIMED_WAITING(限时等待)对应操作系统中 “可定时唤醒的阻塞状态”
- 将该线程从 “就绪队列”(可被 CPU 调度的线程队列)中移除,放入 “定时等待队列”(专门存放限时等待线程的内核队列)。
- 为该线程注册一个 内核定时器,记录等待的截止时间(当前时间 + 超时时间)。
当以下两种情况发生时,操作系统会将线程从 “定时等待队列” 移回 “就绪队列”,使其重新具备被调度的资格:
- 情况 1:等待时间自然结束
内核定时器检测到 “当前时间 ≥ 线程的等待截止时间” 时,会触发唤醒操作:
将线程从 “定时等待队列” 中移除,恢复其状态为 “就绪态”(如 Linux 的 TASK_RUNNING)。
将线程加入 “就绪队列”,等待 CPU 调度器分配时间片。 - 情况 2:线程被中断(如其他线程调用 interrupt())
Java 的 interrupt() 本质是向线程发送一个 “中断信号”,操作系统收到该信号后:
若线程处于 “定时等待队列” 中,会立即将其唤醒,从等待队列移至就绪队列。
同时,JVM 会捕获该中断信号,在 Java 层面抛出 InterruptedException,让线程退出等待状态。
1.TIMED_WAITING vs WAITING:
两者都是 “等待状态”,但 TIMED_WAITING 是有明确等待时长的(如 sleep(1000)、wait(1000)),而 WAITING 是无限期等待(如 wait()、join() 不带超时参数),需被主动唤醒(如 notify())才能恢复。
2.TIMED_WAITING vs BLOCKED:
BLOCKED 状态是线程因竞争锁失败而阻塞(等待获取锁),而 TIMED_WAITING 是线程因主动调用休眠 / 等待方法而暂停(如 sleep()、wait(millis))。