Java中线程的生命周期可以分为以下几个阶段:
(1)新建(New):
当我们创建一个Thread对象时,线程处于新建状态。此时线程还没有开始执行,也没有分配到系统资源。
(2)就绪(Runnable):
当调用线程的start()方法后,线程进入就绪状态。此时线程已经被系统接受,等待分配CPU时间片来执行。注意,就绪状态并不意味着线程立即开始执行,具体的执行时间由线程调度器决定。线程调度的细节依赖于操作系统提供的服务。
(3)运行(Running):
当线程获得CPU时间片后,进入运行状态。此时线程正在执行任务的代码,执行完毕后可能继续运行,也可能进入阻塞状态。
(4)阻塞(Blocked):
线程在执行过程中,可能因为某些原因而暂时停止执行。常见的情况包括等待I/O操作完成、等待获取锁、等待其他线程通知等。当这些条件满足时,线程将进入阻塞状态。一旦条件满足,线程将重新进入就绪状态,等待再次获取CPU时间片。
(5)等待(Waiting):
线程在某些特定条件下主动暂停执行,进入等待状态。例如,调用Object.wait()、Thread.join()、LockSupport.park()等方法会导致线程进入等待状态。需要其他线程显式地唤醒等待线程才能继续执行。
(6)超时等待(Timed Waiting):
与等待状态类似,但是在一定时间后会自动恢复到就绪状态。例如,调用Thread.sleep()、Object.wait(long)、Thread.join(long)等方法可以使线程进入超时等待状态。
(7)终止(Terminated):
线程执行完任务或者发生异常时,线程进入终止状态。一旦线程终止,它将不再执行。
需要注意的是,线程的状态之间可以相互转换,具体的转换由Java虚拟机和操作系统决定。我们可以使用Thread类提供的方法来获取线程的状态,例如getState()方法可以获取线程的当前状态。同时,我们可以使用suspend()、resume()等方法来控制线程的暂停和恢复。不过这些方法已经被标记为过时,不推荐使用,因为它们可能导致线程死锁和不确定的行为。