“全栈2019”Java多线程第十章:Thread.State线程状态详解

261 阅读10分钟

难度

初级

学习时间

30分钟

适合人群

零基础

开发语言

Java

开发环境

  • JDK v11
  • IntelliJ IDEA v2018.3

友情提示

  • 本教学属于系列教学,内容具有连贯性,本章使用到的内容之前教学中都有详细讲解。
  • 本章内容针对零基础或基础较差的同学比较友好,可能对于有基础的同学来说很简单,希望大家可以根据自己的实际情况选择继续看完或等待看下一篇文章。谢谢大家的谅解!

1.什么叫线程状态?

前面在《“全栈2019”Java多线程第五章:线程睡眠sleep()方法详解》一章中讲了如何暂时停止执行线程。

《“全栈2019”Java多线程第六章:中断线程interrupt()方法详解》一章中又讲了如何停止线程。

《“全栈2019”Java多线程第七章:等待线程死亡join()方法详解》一章中讲了如何让一个线程等待另一个线程执行完毕再执行

《“全栈2019”Java多线程第八章:放弃执行权yield()方法详解》一章中讲了如何让一个线程放弃执行权。

《“全栈2019”Java多线程第九章:判断线程是否存活isAlive()详解》一章中讲了如何判断一个线程是否存活

现在我们来讲解线程状态

我们不禁要问:什么叫线程状态?

线程在某一时间点的状态。

状态怎么理解?

比如,线程正在执行,线程正在睡眠,线程正在等待,线程已执行完毕...等等。

2.在Java中有对应的类来描述线程状态吗?

有,是Thread类的内部类:Thread.State。

“全栈2019”Java多线程第十章:Thread.State线程状态详解

3.Thread.State内部类描述了线程几种状态?

描述了线程6种状态:

Thread.State.NEW;

Thread.State.RUNNABLE;

Thread.State.BLOCKED;

Thread.State.WAITING;

Thread.State.TIMED_WAITING;

Thread.State.TERMINATED;

4.它们分别代表什么意思?

Thread.State.NEW:尚未启动的线程处于此状态。

Thread.State.RUNNABLE:在Java虚拟机中执行的线程处于此状态。

Thread.State.BLOCKED:被阻塞等待监视器锁定的线程处于此状态。

Thread.State.WAITING:无限期等待另一个线程执行特定操作的线程处于此状态。

Thread.State.TIMED_WAITING:正在等待另一个线程执行最多指定等待时间的操作的线程处于此状态。

Thread.State.TERMINATED:已退出的线程处于此状态。

注:下面会对这6种状态分别进行详细讲解。

5.线程可用同时拥有多种状态吗?

线程在给定时间点只能处于一种状态。

6.这些状态能反映出线程在操作系统中的状态吗?

这些状态是Java虚拟机的状态,不反映任何操作系统线程状态。

7.怎么获取线程的状态?

我们可以通过Thread的getState()方法来获取线程状态。

8.Thread.State内部类

在看getState()方法之前,我们先来看看Thread.State内部类。

Thread.State内部类是一个枚举类(不清楚什么是枚举类的小伙伴后续我们马上会讲解到):

“全栈2019”Java多线程第十章:Thread.State线程状态详解

将注释翻译成中文:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

去掉注释版:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

Thread.State内部类作用就是描述线程状态。

9.获取线程状态getState()方法

在Thread类中,我们可以通过getState()方法来获取线程状态。

getState()方法在Thread类中的源码:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

将注释翻译成中文:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

去掉注释版:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

getState()方法的作用是获取线程状态。

访问权限

public:getState()方法访问权限是公开的。

State:getState()方法返回State类型的值。State是一个枚举类,它里面每一个值都是State类型,所以返回的每一个值都是State类型。

getState()方法只能被对象调用。

参数

无。

抛出的异常

无。

应用

我们先来创建一个线程:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

然后调用它的getState()方法:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

运行程序,执行结果:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

从运行结果来看,我们的线程现在处于Thread.State.NEW:尚未启动的线程处于此状态。

接下来,我们来启动线程看看:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

运行程序,执行结果:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

从运行结果来看,我们的线程现在处于Thread.State.RUNNABLE:在Java虚拟机中执行的线程处于此状态。

好了,接着我们分别来说说这6种线程状态。

10.Thread.State.NEW

Thread.State.NEW:尚未启动的线程处于此状态。

通俗来说,就是我们创建Thread对象时,线程的状态。

演示:

请让线程处于Thread.State.NEW状态。

请观察程序代码及结果。

代码:

Main类:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

结果:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

从运行结果来看,我们的线程正是Thread.State.NEW:尚未启动的线程处于此状态。

11.Thread.State.RUNNABLE

Thread.State.RUNNABLE:在Java虚拟机中执行的线程处于此状态。

通俗来说,就是我们创建Thread对象以后,启动线程时,线程的状态。

演示:

请让线程处于Thread.State.RUNNABLE状态。

请观察程序代码及结果。

代码:

Main类:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

结果:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

从运行结果来看,我们的线程正是Thread.State.RUNNABLE:在Java虚拟机中执行的线程处于此状态。

12.Thread.State.BLOCKED

Thread.State.BLOCKED:被阻塞等待监视器锁定的线程处于此状态。

通俗来说,线程进入Thread.State.BLOCKED状态只有一种可能:执行同步代码块/方法。

来演示一下。

演示:

请让线程处于Thread.State.BLOCKED状态。

请观察程序代码及结果。

代码:

Main类:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

结果:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

从运行结果来看,符合我们预期。

回顾程序代码,看看需要注意的代码片段。

首先我们在线程中使用到了synchronized关键字,因为被synchronized关键字所修饰的代码块/方法才能被称之为同步代码块/方法,所以这里大家需要注意下:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

被synchronized关键字修饰的代码块叫同步代码块

“全栈2019”Java多线程第十章:Thread.State线程状态详解

我们在同步代码块里面计算从0加到100000的结果,目的就是让线程多执行一会:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

接着,我们看看线程之外做了什么。

我们启动了线程:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

然后,我们声明了一个线程状态变量:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

接着,我们使用了do-while循环,循环条件是当thread线程没有处于Thread.State.TERMINATED状态时(即线程没有执行完毕时),就一直循环,直到thread线程处于Thread.State.TERMINATED状态为止:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

执行结果:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

结果显示,我们线程从Thread.State.RUNNABLE状态进入Thread.State.BLOCKED状态,最后进入Thread.State.TERMINATED状态。也就是从运行状态进入锁定状态,最后进入退出状态。

13.Thread.State.WAITING

Thread.State.WAITING:无限期等待另一个线程执行特定操作的线程处于此状态。

什么叫线程被无限期等待

就是调用Object的wait()方法。当然了,造成线程无限期等待还有很多方法:

  • 未超时的Object.wait()方法
  • 未超时的Thread.join()方法
  • LockSupport.park()方法

注:未超时就是没有具体明确要等多长时间。因为Object.wait()方法和Thread.join()方法都可以设置等待多长时间之后就可以不等了,所以这里希望大家注意一下。

这里只是列举一种方法来演示一下。

演示:

请让线程处于Thread.State.WAITING状态。

请观察程序代码及结果。

代码:

Main类:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

结果:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

从运行结果来看,符合我们预期。

回顾程序代码,看看需要注意的代码片段。

首先我们在线程中使用到了synchronized关键字,因为wait()方法需要配合synchronized关键字使用,所以这里大家需要注意下:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

被synchronized关键字修饰的代码块叫同步代码块

“全栈2019”Java多线程第十章:Thread.State线程状态详解

我们在特别代码块里面调用了wait()方法使线程等待:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

此后,没有我们主动唤醒或中断此线程,它就一直在这等。

接着,我们看看线程之外做了什么。

我们启动了线程:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

然后,我们声明了一个线程状态变量:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

接着,我们使用了do-while循环,循环条件是当thread线程没有处于Thread.State.WAITING状态时,就一直循环,直到thread线程处于Thread.State.WAITING状态为止:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

执行结果:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

结果显示,我们线程从Thread.State.RUNNABLE状态进入Thread.State.WAITING状态。也就是从运行状态进入阻塞状态。

14.Thread.State.TIMED_WAITING

Thread.State.TIMED_WAITING:正在等待另一个线程执行最多指定等待时间的操作的线程处于此状态。

相对于上一小节的无限期等待的Thread.State.WAITING状态,我们这一小节的有限期等待Thread.State.TIMED_WAITING状态就更加容易理解了。

可以让线程处于状态的方法有:

  • Thread.sleep()方法
  • 超时的Object.wait()方法
  • 超时的Thread.join()方法
  • LockSupport.parkNanos()方法
  • LockSupport.parkUntil()方法

这里我们只演示其中的一种,那就是Thread.sleep()方法。在《“全栈2019”Java多线程第五章:线程睡眠sleep()方法详解》一章中,我们也进行了讲解。

演示:

请让线程处于Thread.State.TIMED_WAITING状态。

请观察程序代码及结果。

代码:

Main类:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

结果:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

从运行结果来看,符合预期。

回顾程序代码,看看需要注意的代码片段。

首先,我们在线程中使用sleep()方法让线程睡3秒钟:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

然后,我们启动了线程:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

接着,我们声明了一个线程状态变量:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

然后,我们使用了do-while循环,循环条件是当thread线程没有处于Thread.State.TERMINATED状态时(即线程没有执行完毕时),就一直循环,直到thread线程处于Thread.State.TERMINATED状态为止:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

执行结果:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

结果显示,我们线程从Thread.State.TIMED_WAITING状态进入Thread.State.RUNNABLE状态,最后进入Thread.State.TERMINATED状态。也就是从超时等待状态进入运行状态,最后进入退出状态。

15.Thread.State.TERMINATED

Thread.State.TERMINATED:已退出的线程处于此状态。

已退出:线程run()执行完毕或返回。

返回:return。

这个状态最简单,就是我们线程里面的run()方法执行完毕或者return。

来演示一下。

演示:

请让线程处于Thread.State.TERMINATED状态。

请观察程序代码及结果。

代码:

Main类:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

结果:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

从运行结果来看,符合预期。

回顾程序代码,看看需要注意的代码片段。

首先,我们在线程中只有一行代码:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

然后,我们启动了线程:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

然后,我们使用while无限循环获取线程状态:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

执行结果:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

精简一下结果:

“全栈2019”Java多线程第十章:Thread.State线程状态详解

结果显示,我们线程从Thread.State.RUNNABLE状态进入Thread.State.TERMINATED状态。也就是从运行状态进入退出状态。

总结

  • getState()方法的作用是获取线程状态。
  • Thread.State.NEW:尚未启动的线程处于此状态。
  • Thread.State.RUNNABLE:在Java虚拟机中执行的线程处于此状态。
  • Thread.State.BLOCKED:被阻塞等待监视器锁定的线程处于此状态。
  • Thread.State.WAITING:无限期等待另一个线程执行特定操作的线程处于此状态。
  • Thread.State.TIMED_WAITING:正在等待另一个线程执行最多指定等待时间的操作的线程处于此状态。
  • Thread.State.TERMINATED:已退出的线程处于此状态。

至此,Java中获取线程状态getState()方法相关内容讲解先告一段落,更多内容请持续关注。

答疑

如果大家有问题或想了解更多前沿技术,请在下方留言或评论,我会为大家解答。

上一章

“全栈2019”Java多线程第九章:判断线程是否存活isAlive()详解

下一章

“全栈2019”Java多线程第十一章:线程优先级详解

学习小组

加入同步学习小组,共同交流与进步。

  • 方式一:关注头条号Gorhaf,私信“Java学习小组”。
  • 方式二:关注公众号Gorhaf,回复“Java学习小组”。

全栈工程师学习计划

关注我们,加入“全栈工程师学习计划”。

“全栈2019”Java多线程第十章:Thread.State线程状态详解

版权声明

原创不易,未经允许不得转载!