【深入浅出Java并发编程指南】「难点 - 核心 - 遗漏」线程状态流转及生命周期的技术指南(知识点串烧)
前提介绍
本章主要介绍相关线程声明周期的转换机制以及声明周期的流转关系以及相关AQS的实现和相关的基本原理,配合这相关官方文档的中英文互译的介绍。
线程状态流转及生命周期
当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态。在线程的生命周期中,它要经过新建(New)、就绪/可运行状态(Runnable)、阻塞(Blocked)和等待(Wait)、时间等待(Time_wait)、终止状态(Terminate)六种状态。尤其是当线程启动以后,它不能一直“霸占”着CPU独自运行,所以CPU需要在多条线程之间切换,于是线程状态也会多次在运行、阻塞之间切换。
下图借鉴于官方网站:
生命周期的六种状态
一个事物从出生的那一刻开始到最终死亡中间的整个过程.在事物的漫长的生命周期过程中,总会经历不同的状态(婴儿状态/青少年状态/中年状态/老年状态…).线程也是有生命周期的,也是存在不同的状态的,状态相互之间的转换。
线程对象的状态存放在Thread类的内部类(State)中:
public enum State {/*** Thread state for a thread which has not yet started.*/NEW,/*** Thread state for a runnable thread. A thread in the runnable* state is executing in the Java virtual machine but it may* be waiting for other resources from the operating system* such as processor.*/RUNNABLE,/*** Thread state for a thread blocked waiting for a monitor lock.* A thread in the blocked state is waiting for a monitor lock* to enter a synchronized block/method or* reenter a synchronized block/method after calling* {@link Object#wait() Object.wait}.*/BLOCKED,/*** Thread state for a waiting thread.* A thread is in the waiting state due to calling one of the* following methods:* <ul>* <li>{@link Object#wait() Object.wait} with no timeout</li>* <li>{@link #join() Thread.join} with no timeout</li>* <li>{@link LockSupport#park() LockSupport.park}</li>* </ul>** <p>A thread in the waiting state is waiting for another thread to* perform a particular action.** For example, a thread that has called <tt>Object.wait()</tt>* on an object is waiting for another thread to call* <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on* that object. A thread that has called <tt>Thread.join()</tt>* is waiting for a specified thread to terminate.*/WAITING,/*** Thread state for a waiting thread with a specified waiting time.* A thread is in the timed waiting state due to calling one of* the following methods with a specified positive waiting time:* <ul>* <li>{@link #sleep Thread.sleep}</li>* <li>{@link Object#wait(long) Object.wait} with timeout</li>* <li>{@link #join(long) Thread.join} with timeout</li>* <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>* <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>* </ul>*/TIMED_WAITING,/*** Thread state for a terminated thread.* The thread has completed execution.*/TERMINATED;}
注意:Thread.State类其实是一个枚举类.因为线程对象的状态是固定的,只有6种,此时使用枚举来表示是。
新建(new Thread)
当创建Thread类的一个实例(对象)时,此线程进入新建状态(未被启动)。
使用new创建一个线程对象,仅仅在堆中分配内存空间,在调用start方法之前。 新建状态下,线程压根就没有启动,仅仅只是存在一个线程对象而已.Thread t = new Thread();
此时t就属于新建状态当新建状态下的线程对象调用了start方法,此时从新建状态进入可运行状态.线程对象的start方法只能调用一次,否则报错:IllegalThreadStateException.
例如
Thread t1=new Thread();
可运行(runnable)
分成两种子状态,ready和running。分别表示就绪状态和运行状态。
就绪状态
线程对象调用start方法之后,等待JVM的调度(此时该线程并没有运行),这时候线程处于等待CPU分配资源阶段,谁先抢的CPU资源,谁开始执行,换句话说线程已经被启动,正在等待被分配给CPU时间片,也就是说此时线程正在就绪队列中排队等候得到CPU资源。
运行状态
线程对象获得JVM调度,如果存在多个CPU,那么允许多个线程并行运行
被转换成Terminated状态,比如调用 stop() 方法;
被转换成Blocked状态,比如调用了sleep, wait 方法被加入 waitSet 中;
被转换成Blocked状态,如进行 IO 阻塞操作,如查询数据库进入阻塞状态;
被转换成Blocked状态,比如获取某个锁的释放,而被加入该锁的阻塞队列中;
该线程的时间片用完,CPU 再次调度,进入Runnable状态;
线程主动调用 yield 方法,让出 CPU 资源,进入Runnable状态
例如
t1.start();
运行(running)他也从属于Runnable状态,但不在总体状态之内,属于逻辑状态机制
当就绪的线程被调度并获得CPU资源时,便进入运行状态,run方法定义了线程的操作和功能,此时除非此线程自动放弃CPU资源或者有优先级更高的线程进入,线程将一直运行到结束。
注意:
Runnable状态的线程无法直接进入Blocked状态和Terminated状态的。只有处在Running状态的线程,换句话说,只有获得CPU调度执行权的线程才有资格进入Blocked状态和Terminated状态,Runnable状态的线程要么能被转换成Running状态,要么被意外终止。
堵塞(blocked)
正在运行的线程因为某些原因放弃CPU,暂时停止运行,就会进入阻塞状态.此时JVM不会给线程分配CPU,直到线程重新进入就绪状态,才有机会转到运行状态.阻塞状态只能先进入就绪状态,不能直接进入运行状态。
阻塞状态的两种情况:
- 当A线程处于运行过程时,试图获取同步锁时,却被B线程获取.此时JVM把当前A线程存到对象的锁池中,A线程进入阻塞状态.
- 当线程处于运行过程时,发出了IO请求时,此时进入阻塞状态.
由于某种原因导致正在运行的线程让出CPU并暂停自己的执行,即进入堵塞状态。
被转换成Terminated状态,比如调用 stop() 方法,或者是 JVM 意外 Crash;
被转换成Runnable状态,阻塞时间结束,比如读取到了数据库的数据后;
完成了指定时间的休眠,进入到Runnable状态;
正在wait中的线程,被其他线程调用notify/notifyAll方法唤醒,进入到Runnable状态;
线程获取到了想要的锁资源,进入Runnable状态;
线程在阻塞状态下被打断,如其他线程调用了interrupt方法,进入到Runnable状态;
等待状态(waiting)
(等待状态只能被其他线程唤醒):
此时使用的无参数的wait方法,
- 当线程处于运行过程时,调用了wait()方法,此时JVM把当前线程存在对象等待池中.
计时等待状态(timed waiting)
(使用了带参数的wait方法或者sleep方法)
- 当线程处于运行过程时,调用了wait(long time)方法,此时JVM把当前线程存在对象等待池中.
- :当前线程执行了sleep(long time)方法.
终止状态(terminated)
通常称为死亡状态,表示线程终止.
- 正常执行完run方法而退出(正常死亡).
- 遇到异常而退出(出现异常之后,程序就会中断)(意外死亡).
- JVM 异常结束,所有的线程生命周期均被结束。
线程一旦终止,就不能再重启启动,否则报错(IllegalThreadStateException).
不推荐使用的线程方法
在Thread类中过时的方法(因为存在线程安全问题,所以弃用了):
- void suspend() :暂停当前线程
- void resume() :恢复当前线程
- void stop() :结束当前线程
给大家结合官网在进行一个中文解释的状态流转图:
【深入浅出Java并发编程指南】「难点 - 核心 - 遗漏」线程状态流转及生命周期的技术指南(知识点串烧)相关推荐
- 【Java进阶营】Java技术专题「难点-核心-遗漏」Java线程状态流转及生命周期的技术指南(知识点串烧)
前提介绍 本章主要介绍相关线程声明周期的转换机制以及声明周期的流转关系以及相关AQS的实现和相关的基本原理,配合这相关官方文档的中英文互译的介绍. 线程状态流转及生命周期 当线程被创建并启动以后,它既 ...
- Java 并发编程(四):如何保证对象的线程安全性
本篇来谈谈 Java 并发编程:如何保证对象的线程安全性. 01.前言 先让我吐一句肺腑之言吧,不说出来会憋出内伤的.<Java 并发编程实战>这本书太特么枯燥了,尽管它被奉为并发编程当中 ...
- Java并发编程实战读书笔记(一)——线程安全性、对象共享
一.线程安全性 一个对象是否需要是线程安全的,取决于它是否被多个线程访问. 当多个线程访问,并且其中有一个执行写入时,必须采用同步机制,Java中主要的同步关键字是 synchronized 独占加锁 ...
- 「测试猿课堂」软件测试的6个生命周期 中高级测试猿必看
一.软件测试生命周期 无论我们测试人员使用哪种测试方法,都始终需要遵循特定的测试生命周期.软件测试生命周期有助于让团队专注于产品需求和开发功能,循序渐进,并且程序健康成长. >> 下载30 ...
- Java 并发编程解析 | 如何正确理解Java领域中的多线程模型,主要用来解决什么问题?
苍穹之边,浩瀚之挚,眰恦之美: 悟心悟性,善始善终,惟善惟道! -- 朝槿<朝槿兮年说> 写在开头 我国宋代禅宗大师青原行思在<三重境界>中有这样一句话:" 参禅之初 ...
- Java并发编程有多难?这几个核心技术你掌握了吗?
本文主要内容索引 1.Java线程 2.线程模型 3.Java线程池 4.Future(各种Future) 5.Fork/Join框架 6.volatile 7.CAS(原子操作) 8.AQS(并发同 ...
- Java并发编程中的若干核心技术,向高手进阶
来源:http://www.jianshu.com/p/5f499f8212e7 引言 本文试图从一个更高的视角来总结Java语言中的并发编程内容,希望阅读完本文之后,可以收获一些内容,至少应该知道在 ...
- JAVA并发编程实践笔记
2019独角兽企业重金招聘Python工程师标准>>> JAVA并发编程实践笔记 博客分类: java JAVA并发编程实践笔记 1, 保证线程安全的三种方法: a, 不要跨 ...
- Java并发编程工具类:CountDownLatch、CyclicBarrier、Semaphore
在jdk5中,java提供了一些非常有用的辅助工具类,包括CountDownLatch和CyclicBarrier(两者都可以实现线程之间的通信).Semaphore(控制方法被线程访问的数量),他们 ...
最新文章
- 关卡CyclicBarrier的使用
- 3v stm32 供电 晶振起振_避免stm32rtc晶振不能起振的设计参考
- vue路由切换和用location切换url的区别
- js中json的创建和解析
- java impala_Java实现impala操作kudu
- newifi3高恪魔改最新_12.22达达最新球球id账号呆瓜表
- fastjson 检测json格式_FastJson对于JSON格式字符串、JSON对象及JavaBean之间的相互转换...
- 某游戏服务运维架构进化史(上云方案)
- shell与shell脚本
- svn /lib64/libz.so.1: no version information available
- 图解 Linux 最常用命令
- 机器学习第九章聚类Kmeans练习(西瓜数据集4.0)
- 要如何给PDF解密?这几个操作简单的方法可以试试
- chrome 浏览器地址栏快速搜索设置
- 两代 2011/2014 Mac Mini 硬盘SSD性能提升研究。(SSD固态硬盘研究)
- 去掉右键烦人的多余菜单项
- 一篇网络流的好blog
- Linux使用shell脚本批量拷贝文件
- php微信公众点歌台,PHP实现微信公众平台音乐点播功能
- HTML的背景颜色和背景图片
热门文章
- 2014 ChinaJoy落下帷幕 十大年度热门事件盘点
- 衣服、商品、商城网站模板首页,仿U袋网,vue+elementui简洁实现(二)
- AR模型(Autoregress)
- 去水印小程序API接口和搭建教程
- GdPicture.NET SDK Crack,编辑、捕获或打印文档
- Apache与Tomcat关系和区别
- 拂面微风之项目一:皖新传媒(新华书店)项目
- BeautfulSoup详解
- SAP中外协加工模式下原材料供应商直接发料给外协加工商的操作方法
- shared_ptr与make_shared的用法