- Java 线程生命周期中都包含哪些状态?
- 生命周期中各个状态都是什么含义?
- 状态是如何转化的?
线程的生命周期,对于多线程开发是非常重要的,也是面试中常见的问题。
下面我们就梳理一下线程的生命周期,快速理解掌握。
线程生命周期总览
这是线程生命周期的总览图:
在图中可以看到一个线程的所有状态,我们先了解一下这些状态的含义。
- NEW - 初始状态,一个新创建的线程,还没开始执行。
- RUNNABLE - 可执行的状态,要么是在执行,要么是一切就绪等待执行,例如等待分配CPU时间。
- WAITING - 等待状态,等待其他的线程去执行特定的动作,没有时间限制。
- TIMED_WAITING - 限时等待状态,等待其他的线程去执行特定的动作,这个是在一个指定的时间范围内。
- BLOCKED - 阻塞状态,等待锁,以便进入同步块儿。
- TERMINATED - 终止状态,线程执行结束。
如上图,这些状态大体上可以分为 2 个部分:
(1)正常过程
创建线程(NEW),然后线程做自己的工作(RUNNABLE),做完之后就终止了(TERMINATED)。
(2)非正常情况
线程执行的时候遇到了点问题,需要等待(WAITING、TIMED WAITING)一会儿,或者被别人阻塞了(BLOCKED)。
线程结束等待之后,也可能进入阻塞状态。
非正常情况结束之后,线程再继续执行自己的工作,所以箭头也好理解了。
NEW
NEW 线程是被创建出来后还没执行的。
这个状态直到调用了 start()
方法后变化。
下面的代码显示了一个 NEW 状态的线程:
代码语言:javascript复制Thread t = new MyThread();
RUNNABLE
我们创建一个线程,然后调用了 start()
方法,那么这个线程就从 NEW 变为了 RUNNABLE 状态。
处于 RUNNABLE 状态的线程可能正在运行,也可能在等待系统为其分配资源。
JVM 中的 Thread-Scheduler(线程调度器)会为每个线程分配一个固定的执行时间,所以一个线程一次就只执行一段时间,时间到了之后,就会让其他的 RUNNABLE 状态的线程执行。
下面的代码显示了 RUNNABLE 状态:
代码语言:javascript复制Thread t = new MyThread();
t.start();
WAITING
一个线程在等待其他线程执行特定动作的时候就处于 WAITING 状态。
调用下列方法后就会进入 WAITING 状态:
- object.wait()
- thread.join()
- LockSupport.park()
例如:
我们创建并启动 1个线程 threadA
threadA 又创建了 threadB,然后启动
在 threadA 里面调用了 threadB.join(),那么这时 threadA 就进入了 WAITING 状态,直到 threadB 执行结束。
TIMED WAITING
和 WAITING 一样也是等待状态,不同是 WAITING 没有时间限制,而 TIMED_WAITING 有等待时间限制。
通过下面的方法可以进入 TIMED_WAITING 状态:
- thread.sleep(long millis)
- wait(int timeout) or wait(int timeout, int nanos)
- thread.join(long millis*)*
- LockSupport.parkNanos
- LockSupport.parkUntil
BLOCKED
一个线程要执行的代码被其他线程锁了,所以在阻塞在这儿了,需要等待人家开锁后才能执行。
例如:
我们创建 2 个线程 threadA、threadB
有一个同步方法 A(),意味着一次只能有一个线程访问
这2个线程都要执行 A(),threadA 先进去执行了,那么 threadB 就进不去了,处于 BLOCKED 状态。
TERMINATED
这是线程生命结束的状态,一个线程的结束,可能是正常执行完成了,也可能是异常终止了。
小结
最终线程的生命周期图如下:
梳理一下整体的思路:
(1)正常情况
创建线程(NEW)=> 线程工作(RUNNABLE)=> 线程终止(TERMINATED)
(2)非正常情况
线程执行时需要和其他线程配合执行,需要等待(WAITING、TIMED WAITING)
线程执行时还可能与其他线程竞争,被阻塞(BLOCKED)
非正常情况结束后,就要回到 RUNNABLE 状态,继续执行。
OK 线程生命周期的主要内容就这么多,思路梳理好之后还是很好理解的。
感谢阅读,希望对你有所帮助,欢迎点赞转发,非常感谢 !!!