录屏 音乐 摸鱼 压图
在Java中,线程的启动必须调用Thread实例的start()方法,而非直接调用run()方法。原因如下:
run()方法只是用户编写的普通业务逻辑,不具备操作系统级别的线程调度能力;直接调用它相当于在当前线程内做一次顺序方法调用,不会创建新的调用栈。
start()方法由JVM实现,会完成与操作系统的交互:分配native线程、初始化线程私有内存、将线程状态从NEW切换为RUNNABLE,并最终回调run()方法。
若直接执行run(),程序中依旧只有一条执行路径(通常是main线程),既不能并发,也无法利用多核CPU资源,从而失去创建线程的意义。
Java规范明确规定:一个Thread对象的start()只能被成功调用一次。第二次及以后的调用将抛出java.lang.IllegalThreadStateException(运行时异常)。
该限制基于以下考虑:
线程生命周期不可逆。一旦线程到达TERMINATED状态,其内部状态已被回收,无法再次启动。
若允许多次启动,将破坏线程安全模型:旧栈帧、监视器锁、中断状态等资源均处于不确定状态,极易产生竞态条件或内存可见性问题。
JDK5以后,Thread.State枚举明确定义了6种状态:
NEW:已创建Thread实例,尚未调用start()。
RUNNABLE:线程正在JVM中执行,或已就绪等待操作系统分配CPU时间片(Java把操作系统层面的running+ready统一为RUNNABLE)。
BLOCKED:线程等待获取监视器锁(synchronized)。
WAITING:线程无条件等待,直至其他线程显式唤醒(Object.wait、Thread.join、LockSupport.park等)。
TIMED_WAITING:带超时限制的等待(Thread.sleep、Object.wait(timeout)、LockSupport.parkNanos等)。
TERMINATED:run()方法正常结束或异常退出,线程生命周期结束。
状态转换是单向不可逆的。一旦进入TERMINATED,任何试图回到RUNNABLE的操作(包括再次调用start())都会被JVM拒绝并抛出IllegalThreadStateException。
始终通过newThread(...).start()启动新线程;如需重复执行任务,请使用线程池(ExecutorService)或创建新的Thread实例。
在并发场景下,优先使用java.util.concurrent包提供的工具(Executor、Future、ThreadPoolExecutor等),避免手动管理裸线程。
若需保证线程安全,请结合同步机制(synchronized、java.util.concurrent.locks)与可见性语义(volatile、final、Atomic*)进行设计。