start() 方法是 Java 多线程并发执行的关键入口,它触发 JVM 创建操作系统级线程并自动调用 run(),而直接调用 run() 仅为同步方法调用,不产生新线程。

Java 中的 start() 方法是真正让多线程并发执行的关键入口,它不是简单地调用任务逻辑,而是触发 JVM 底层线程调度机制,使任务在独立线程中运行。
start() 启动新线程的本质
调用 start() 时,JVM 会为该 Thread 对象分配操作系统级线程资源,将其状态从 New 变为 Runnable,并交由系统调度器安排执行。此时,run() 方法会在新线程中被自动调用,与主线程或其他线程并行运行。
- start() 是 native 方法,依赖 JVM 和 OS 协同完成线程创建
- 每个 Thread 实例只能 start() 一次;重复调用抛出
IllegalStateException - 一旦线程终止(run() 执行完毕或异常退出),无法再次 start()
run() 直接调用 ≠ 多线程
如果跳过 start(),直接写 thread.run(),那就只是普通方法调用:run() 代码仍在当前线程同步执行,不会产生新线程,也谈不上并发。
- 例如:主线程调用
t.run(),所有输出都发生在 main 线程里 - 而
t.start()后,t 的 run() 在新线程中执行,main 和 t 可能交替打印
必须配合正确的线程定义方式
start() 能起作用的前提,是 Thread 对象已正确绑定任务逻辑——这通常通过两种主流方式实现:
立即学习“Java免费学习笔记(深入)”;
- 继承 Thread 类:重写 run() 方法,new 子类实例后调用 start()
- 实现 Runnable 接口:实现 run() 方法,再用它构造 Thread 对象,然后 start()
无论哪种方式,最终都是靠 Thread.start() 触发并发;Callable + FutureTask 等高级方式,底层依然依赖 start() 启动封装后的 Thread。
并发执行的典型表现
多个线程调用 start() 后,它们的 run() 方法会“看起来同时运行”——实际取决于 CPU 核心数、调度策略和任务耗时。例如:
- 主线程启动两个子线程,各自循环打印 10 次
- 输出顺序不确定,可能出现交叉(如 t1-1、main-1、t2-1、t1-2…)
- 这种不确定性正是并发执行的直观体现


















