Java线程的生命周期可以分为五个状态,分别是新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)和终止(Terminated)。
线程状态的转换如下:
新建(New)状态
在新建线程对象后,该线程对象还没有被分配 CPU 时间片,不会执行任何代码。此时线程对象处于 New 状态。
线程对象处于 New 状态时,它的状态可以改变,例如可以调用 start() 方法启动线程,使其进入就绪状态,也可以在新建线程对象时通过调用 setPriority() 方法设置线程的优先级,或者通过调用 setName() 方法设置线程的名称等等。
就绪(Runnable)状态
当线程调用了 start() 方法后,线程对象进入就绪状态,此时它已经分配了 CPU 时间片,并等待系统分配 CPU 时间片开始执行线程代码。处于就绪状态的线程不一定能立即得到 CPU 时间片,它们处于等待状态,直到系统分配到它们所需要的 CPU 时间片。
处于就绪状态的线程通过调度器来决定哪个线程获得 CPU 时间片,线程调度器的调度算法通常是先进先出(FIFO)。
运行(Running)状态
当线程获得了 CPU 时间片后,进入运行状态,此时线程开始真正执行线程代码。线程代码中的指令依次执行,直到程序执行完毕或者执行到 sleep()、wait() 等方法时,线程会进入阻塞状态,直到阻塞条件被解除。
在运行状态下,线程可以执行一些耗时操作,例如计算、循环等等。当线程被分配到的 CPU 时间片用完后,系统会将其转为就绪状态,等待下一次分配 CPU 时间片。
阻塞(Blocked)状态
线程在运行时可能会遇到一些阻塞条件,例如等待 I/O、sleep 等操作。当线程执行这些操作时,线程会进入阻塞状态,它会暂停执行并且释放 CPU 时间片,直到阻塞条件被解除。
在阻塞状态下,线程不能执行任何代码,直到阻塞条件被解除时,线程才会转为就绪状态,等待系统分配 CPU 时间片。
终止(Terminated)状态
线程可能因为两个原因进入终止状态:(1)线程正常执行完毕,或者(2)线程出现了未捕获的异常而意外终止。
线程进入终止状态后,它会释放所有的资源,并且不能再运行任何代码。一旦线程进入了终止状态,就不可能再回到运行状态或阻塞状态了。
例如,可以通过调用 Thread 类的 join() 方法,让主线程等待子线程执行完毕后再终止,以保证线程能够正常退出。