直接调用run()方法不会产生并发效果,因为它只是在当前线程中顺序执行,不启动新线程;而start()才真正触发JVM创建新线程并调度执行run()。

直接调用 run() 方法不会产生并发效果,因为它根本没启动新线程——只是在当前线程里像调用普通方法一样执行了一段代码。
run() 本质上就是一个普通方法
Java 中的 run() 方法没有特殊魔力。它被设计成线程“要做的事”的容器,但本身不带线程创建能力。JVM 不会因为看到你写了 run() 就自动分配栈空间、注册调度器或切换上下文。
- 它没有触发 JVM 的线程生命周期管理(新建 → 就绪 → 运行等)
- 它不申请独立的程序计数器、线程局部变量(ThreadLocal)存储或私有调用栈
- 它的所有变量、异常、执行路径都和当前线程共享,完全同步阻塞
调用 run() = 在主线程里顺序执行
比如你在 main() 方法里写 t.run(),那整个 run() 方法体就压进主线程的调用栈,和 System.out.println("hello") 没区别。
- 输出中的
Thread.currentThread().getName()一定是"main" - 如果
run()里有Thread.sleep(2000),主线程会卡住整整两秒,其他逻辑全得等 - 即使创建了十个
Thread对象并挨个调用.run(),也只有一条执行流,毫无并发可言
start() 才是真正开启线程的“开关”
start() 是 JVM 预留的入口点:它通知底层线程库(如 pthread 或 Windows Thread API)分配资源、注册调度、设置初始状态,并确保后续由新线程去调用 run()。
- 调用
t.start()后,t状态从 NEW 变为 RUNNABLE,进入操作系统就绪队列 - JVM 保证这个
run()一定运行在新分配的栈帧中,与主线程隔离 - 主线程调用
start()后立刻返回,继续往下走,两个线程开始竞争 CPU 时间片
一个典型对比示例
假设你写了:
Thread t1 = new Thread(() -> { System.out.println("A: " + Thread.currentThread().getName()); });
Thread t2 = new Thread(() -> { System.out.println("B: " + Thread.currentThread().getName()); });
t1.run(); // 输出 A: main
t2.run(); // 输出 B: main —— 顺序执行,无并发
t1.start(); // 输出 A: Thread-0(可能)
t2.start(); // 输出 B: Thread-1(可能)—— 并发发生,线程名不同,执行时机不确定

















