「轻阅读」图解 Java 线程生命周期

浅殇忆流年 2020-08-19 14:38:07 ⋅ 842 阅读
  • Java 线程生命周期中都包含哪些状态?

  • 生命周期中各个状态都是什么含义?

  • 状态是如何转化的?

线程的生命周期,对于多线程开发是非常重要的,也是面试中常见的问题。

下面我们就梳理一下线程的生命周期,快速理解掌握。

线程生命周期总览

这是线程生命周期的总览图:

在图中可以看到一个线程的所有状态,我们先了解一下这些状态的含义。

  • NEW  - 初始状态,一个新创建的线程,还没开始执行。
  • RUNNABLE  - 可执行的状态,要么是在执行,要么是一切就绪等待执行,例如等待分配CPU时间。
  • WAITING  - 等待状态,等待其他的线程去执行特定的动作,没有时间限制。
  • TIMED_WAITING  - 限时等待状态,等待其他的线程去执行特定的动作,这个是在一个指定的时间范围内。
  • BLOCKED  - 阻塞状态,等待锁,以便进入同步块儿。
  • TERMINATED  - 终止状态,线程执行结束。

如上图,这些状态大体上可以分为 2 个部分:

(1)正常过程

创建线程(NEW),然后线程做自己的工作(RUNNABLE),做完之后就终止了(TERMINATED)。

(2)非正常情况

线程执行的时候遇到了点问题,需要等待(WAITING、TIMED WAITING)一会儿,或者被别人阻塞了(BLOCKED)。

线程结束等待之后,也可能进入阻塞状态。

非正常情况结束之后,线程再继续执行自己的工作,所以箭头也好理解了。

NEW

NEW 线程是被创建出来后还没执行的。

这个状态直到调用了 start() 方法后变化。

下面的代码显示了一个 NEW 状态的线程:

Thread t = new MyThread();

RUNNABLE

我们创建一个线程,然后调用了 start() 方法,那么这个线程就从 NEW 变为了 RUNNABLE状态。

处于 RUNNABLE 状态的线程可能正在运行,也可能在等待系统为其分配资源。

JVM 中的 Thread-Scheduler(线程调度器)会为每个线程分配一个固定的执行时间,所以一个线程一次就只执行一段时间,时间到了之后,就会让其他的 RUNNABLE 状态的线程执行。

下面的代码显示了 RUNNABLE 状态:

Thread t = new MyThread();t.start();

WAITING

一个线程在等待其他线程执行特定动作的时候就处于 WAITING 状态。

调用下列方法后就会进入 WAITING 状态:

  1. object.wait()
  2. thread.join()
  3. LockSupport.park()

例如:

我们创建并启动 1个线程 threadA

threadA 又创建了 threadB,然后启动

 threadA 里面调用了 threadB.join(),那么这时 threadA 就进入了 WAITING 状态,直到 threadB 执行结束。

TIMED WAITING

 WAITING 一样也是等待状态,不同是 WAITING 没有时间限制,而 TIMED_WAITING 有等待时间限制。

通过下面的方法可以进入 TIMED_WAITING 状态:

  1. thread.sleep(long millis)
  2. wait(int timeout)  or   wait(int timeout, int nanos)
  3. thread.join(long  millis*)*
  4. LockSupport.parkNanos
  5. LockSupport.parkUntil

BLOCKED

一个线程要执行的代码被其他线程锁了,所以在阻塞在这儿了,需要等待人家开锁后才能执行。

例如:

我们创建 2 个线程 threadA、threadB

有一个同步方法 A(),意味着一次只能有一个线程访问

这2个线程都要执行 A()threadA 先进去执行了,那么 threadB 就进不去了,处于 BLOCKED状态。

TERMINATED

这是线程生命结束的状态,一个线程的结束,可能是正常执行完成了,也可能是异常终止了。

小结

最终线程的生命周期图如下:

梳理一下整体的思路:

(1)正常情况

创建线程(NEW)=> 线程工作(RUNNABLE)=> 线程终止(TERMINATED)

(2)非正常情况

线程执行时需要和其他线程配合执行,需要等待(WAITING、TIMED WAITING)

线程执行时还可能与其他线程竞争,被阻塞(BLOCKED)

非正常情况结束后,就要回到 RUNNABLE 状态,继续执行。

OK 线程生命周期的主要内容就这么多,思路梳理好之后还是很好理解的。

感谢阅读,希望对你有所帮助,欢迎点赞转发,非常感谢 !!!



全部评论: 0

    我有话说:

    阅读】基于 Java Spring cloud的开源在线教育系统调试实战

    转载自:https://www.toutiao.com/i6759167063090004483开篇之前分享

    JavaWeb实战篇:视图化了解多线Wait、NotifyAll使用案例

    内容简介本节针对于我们常听说而不常使用的 wait 和 notify 方法做个生产者和消费者案例效果图多线......

    Java 零注解文档生成工具—smart-doc,看完有替换swagger的冲动

    Tips:喜欢的话可以关注小萌哦~~~今天小萌给大家推荐的一个开源Java Restful API 文档生成

    阅读」京东商城交易系统的演进之路

    原文:https://www.toutiao.com/i6762874634867048963商城服务如图所

    阅读」如何构建可伸缩的Web应用?

    可伸缩性已经成为Web应用程序的DNA!

    阅读」大众点评是如何分表分库的?

    原大众点评的订单单表早就已经突破两百G,由于查询维度较多,即使加了两个从库,优化索引,仍然存在很多查询不理想

    阅读」如何设计移动端屏适配方案

    在众多的移动设备中,前端开发人员如何在不同屏幕大小,不同程度的高清屏下去百分百的还原设计稿,从来都不

    阅读」推荐系统中信息增强的小技巧

    实用的推荐系统的构建经验,如何进行信息增强。

    阅读」轻松理解 Kubernetes 的核心概念

    Kubernetes 迅速成为云环境中软件部署和管理的新标准。

    阅读」4大服务注册发现技术对比

    架构设计中的 CAP 和 BASE 理论

    阅读」“做完”和“做好”的区别

    在工作中,“做完”和“做好”虽然仅一字之差,但前者只是完成了某项工作,而后者则不仅是完成了工作还有一个好的结

    Redis多线演进

    Redis作为一个基于内存的缓存系统,一直以高性能著称,因没有上下文切换以及无锁操作,即使在单线处理情况下,读速度仍可达到11万次/s,写速度达到8.1万次/s。但是,单线的设计也给Redis

    阅读」亿级用户的分布式数据存储解决方案

    分布式数据库和分布式存储是分布式系统中难度最大、挑战最大,也是最容易出问题的地方。互联网公司只有解决分布式数据存储的问题,才能支撑更多次亿级用户的涌入。