Java中启动线程的唯一规范方式是调用Thread实例的start()方法,它会检查线程状态是否为NEW,通过JVM调用本地方法创建原生线程并自动执行run()逻辑;直接调用run()仅是普通方法调用,不产生新线程。
Java 中启动线程的规范方式,就是调用 Thread 实例的 start() 方法。这不是一个可选项,而是唯一符合线程生命周期设计的启动路径。直接调用 run() 方法,本质上只是执行普通方法,不会创建新线程,也不触发 JVM 的线程调度机制。
start() 是启动线程的唯一合法入口
Java 规定每个线程对象只能被启动一次。start() 方法内部会检查线程状态:只有当状态为 NEW(即 threadStatus == 0)时,才允许继续执行;否则立即抛出 IllegalThreadStateException。这个设计强制保证了线程状态的单向流转——从新建 → 就绪 → 运行 → 终止,不可逆、不可重复。
- 调用 start() 后,JVM 会触发本地方法 start0(),由底层操作系统(如 Linux 的 pthread_create 或 Windows 的 CreateThread)真正创建原生线程
- 新线程创建成功后,会自动绑定到对应的 Java Thread 对象,并在该线程上下文中执行 run() 方法中的逻辑
- 主线程调用 start() 只是“发起请求”,不决定执行时机;何时运行由操作系统线程调度器决定
run() 方法不是启动方式,而是任务载体
run() 是一个普通实例方法,定义在线程要执行的具体行为。它本身不具备任何线程管理能力:
- 直接调用 runnable.run() 或 thread.run(),代码仍在当前线程(通常是 main)中同步执行,毫无并发意义
- 重写 run() 是为了填充业务逻辑,但必须通过 start() 才能让这段逻辑在新线程里跑起来
- Runnable 接口的 run() 和 Thread 子类的 run() 语义一致,都只是任务声明,不是执行指令
启动前建议做状态校验(非必需但稳妥)
虽然生产环境一般靠代码结构保障只调用一次 start(),但在调试或关键流程中,可主动判断线程是否处于可启动状态:
立即学习“Java免费学习笔记(深入)”;
- 使用 t.getState() == Thread.State.NEW 判断线程尚未启动
- 注意:getState() 和 start() 之间存在极小时间窗口,不能作为并发控制依据,仅用于诊断或防御性编程
- 更可靠的做法是封装线程启动逻辑,确保每个 Thread 实例只被 start() 一次(例如用标志位或构造即启动)
常见误用与后果
以下操作均违反规范,应避免:
-
重复调用 start():必定抛出 IllegalThreadStateException,程序中断
-
调用已终止线程的 start():状态已是 TERMINATED,同样非法
-
用 run() 替代 start():看似“执行了”,实则无并发,所有逻辑串行跑在主线程
-
在非 NEW 状态下调用 start():比如刚 new 出来就 sleep 了,再 start —— 只要没被启动过,仍合法;但一旦 start 过,哪怕还没真正运行,状态也已改变