start()调用后线程进入runnable状态但未必立即执行run(),通过打印顺序、yield()延迟、时间戳对比及volatile变量可见性可验证调度存在时间差。

可以通过让主线程和新线程交替打印、并配合 Thread.yield() 或短时 sleep(),来直观展示 start() 调用后线程并未立即执行——它只是进入就绪状态,等待 CPU 调度。
用打印顺序证明调度延迟
主线程调用 t.start() 后立刻继续执行自己的代码,而新线程可能在若干毫秒甚至更晚才真正开始运行。关键在于:**start() 返回不等于线程体(run())已执行**。
- 在子线程
run()开头加System.out.println("子线程开始") - 在
start()后紧接System.out.println("start() 已返回") - 多次运行会发现:“start() 已返回” 总是先输出,但“子线程开始”可能滞后几十到几百微秒——这说明线程已启动(状态为 RUNNABLE),但尚未被调度执行
用 Thread.yield() 放大观察效果
yield() 主动让出 CPU,可增加主线程“抢走时间片”的概率,从而拉长子线程实际运行的延迟。
- 主线程在
t.start()后连续调用几次Thread.yield() - 子线程
run()中第一行就打印时间戳(如System.nanoTime()) - 对比主线程调用
start()的时刻与子线程实际打印的时刻,差值往往明显大于 0 —— 证明中间存在调度空档
用 volatile 变量验证可见性与执行时机分离
定义一个 volatile boolean started = false,子线程在 run() 开头设为 true;主线程调用 start() 后立即轮询该变量。
- 你会发现:即使
started仍为false,线程对象的状态已是Thread.State.RUNNABLE - 这说明线程已由 JVM 创建并入队,但其
run()方法尚未被执行——start()和run()的执行存在明确的时间差
补充:查看线程状态辅助判断
调用 t.getState() 可确认线程是否进入就绪态,但无法保证正在运行。
-
t.start()后立刻查状态,通常得到RUNNABLE(注意:不是RUNNING,JVM 没有 RUNNING 状态) -
RUNNABLE表示“可运行”,包括:正在 CPU 上执行,或在就绪队列中等待调度——仅凭状态无法区分二者 - 只有当线程真正开始执行
run()中的第一条语句,才算“运行起来”,而这由操作系统调度器决定,不受 Java 代码控制










