java 线程状态_浅析Java中的线程状态

一、线程的5种状态

2da767b2b714e6dde679cc3404e66c23.png

众所周知,Java的线程状态有5种,分别对应上图中五种不同颜色,下面对这5种状态及状态间的转化做相应的解释:

1. 初始化状态:新建一个线程对象

2. 可运行状态:其他线程调用了该线程对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权

3. 运行状态:可运行状态的线程获得了cpu 时间片(timeslice),执行程序代码

4. 阻塞状态:线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程再次进入可运行状态,才有机会转到运行状态。如图所示,会有三种不同类型的阻塞状态:

  • 等待阻塞:运行中的线程执行wait()方法,线程会进入等待队列中。等待notify()、notifyAll()或interrupt()对其唤醒或中断
  • 同步阻塞:运行中的线程执行在获取同步锁(注:只有synchronized这种方式的锁(monitor锁)才会让线程出现BLOCKED状态,等待ReentrantLock则不会)时,若该锁已被其他线程占用,线程则会进入锁池队列。等待获取到锁
  • 其他阻塞:运行的线程执行sleep()、join(),或触发了I/O请求,该该线程被置为阻塞状态。当sleep()状态超时、join()等待线程终止或超时、I/O处理完成,线程会重新进入可运行状态。

5. 死亡状态:线程执行完或因异常退出run()方法,线程生命周期结束

看完上面的配图和简介,可能会有人对阻塞状态的几种情况有些疑问,下面我们就一点一点解开她的小裙子 图中同样都是Blocked状态,等待队列和锁池是什么鬼?

等待队列和锁池都和wait()、notify()、synchronized有关,wait()和notify()又必须由对象调用且必须写在synchronized同步代码块内。

  1. 等待队列(等待被唤醒):对应等待阻塞。调用obj的wait()方法,则进入等待队列
  2. 锁池(等待抢锁):对应同步阻塞。

a)当前running线程调用对象obj的同步方法时,发现锁被其他线程持有,则直接进入锁池。

b)当前等待队列中阻塞的线程A,等待被线程B唤醒,唤醒后并非直接进去runnable状态,而是进入线程A所对应的锁池中,等待抢到锁。

下图直观描绘了running->等待队列->锁池->runnable间的状态流转,帮助大家理解。

090da299fe2921f4ee786493ae22f7e6.png

怎么样,有没有通透很多?啊!还是有些小迷糊。好,那我们下面从jdk源码中对线程状态的描述进行分析

二、Thread.State枚举类中的BLOCKED、WAITING、TIMED_WAITING

我们打开Jdk源码中Thread类,会发现里面有定义State的枚举,枚举中有:NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED。由于线程中的初始化和死亡状态很短,我们不用太关心,runnable状态暂无歧义。我们只针对BLOCKED、WAITING、TIMED_WAITING三种可能混淆的状态进行分析

首先,上源码

/*** 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,// 受阻塞并且正在等待monitor锁的某一线程的线程状态。/*** 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,// 具有指定等待时间的某一等待线程的线程状态
  1. BLOCKED场景:某一线程在等待monitor lock,比如在等待执行synchronized代码块/方法,这不就相当于进入了我们的锁池阻塞状态吗!;或在synchronized块/方法中循环调用obj的wait()方法,也就是线程在等待进入临界区。
  2. WAITING场景:某一线程因为调用下列方法之一而处于等待状态:
  • 不带超时值的 Object.wait
  • 不带超时值的 Thread.join
  • LockSupport.park 分析:既有可能进入等待队列,也有可能进入其他阻塞的阻塞状态

3. TIMED_WAITING场景:某一线程因为调用以下带有指定正等待时间的方法之一而处于定时等待状态:

  • Thread.sleep(long millis)
  • 带有超时值的 Object.wait
  • 带有超时值的 Thread.join
  • LockSupport.parkNanos
  • LockSupport.parkUntil 分析:既有可能进入等待队列,也有可能进入其他阻塞的阻塞状态。和WAITING区别在于是否指定时间

结合实际编程经验,及工作中所遇到的情形,仔细回味一下上面两个模块的内容,可能就会恍然大悟。

三、并发编程中常用的几个jdk中的api的理解,可能面试常问哦

  1. Thread.sleep(long millis) 静态方法。当前线程调用此方法,使当前线程进入阻塞状态(其他阻塞),但不释放任何锁资源,一定时间后线程自动进入runnable状态。给其它线程执行机会的最佳方式
  2. obj.wait()或obj.wait(long timeout) 当前线程调用某对象的wait()方法,当前线程释放对象锁(wait一定在synchronized代码块/方法中,故一定得到了锁,才进来的此方法),进入阻塞状态(等待队列)。等待notify或wait设置的timeout到期,方可进入另外一个阻塞状态(锁池)。
  3. t.join()或t.join(long millis) 非静态方法。当前线程A执行过程中,调用B线程的join方法,使当前线程进入阻塞状态(其他阻塞),但不释放对象锁,等待B线程执行完后或一定时间millis后,A线程进入runnable状态。
  4. Thread.yield() 静态方法。当前线程调用此方法,使线程由running态进入runnable态,放弃cpu使用权,让cpu再次选择要执行的线程。 注:实际过程中,yield仅仅是让其它具有同等优先级的runnable线程获取执行权,但并不能保证其它具有同等优先级的线程就一定能获得cpu执行权。因为做出让步的当前线程,可能会被cpu再次选中,进入running状态。yield()不会导致阻塞。
  5. 并发编程中为什么使用while循环而不是if()来调用wait方法 当其他获取到该对象锁的线程释放锁时,上面的线程有可能被意外唤醒,但是此时上面线程是不满足条件的,导致它破坏了被锁保护的约束关系,引起意外后果。 用while()方法,就会再次判断条件是不是成立,满足执行条件了,才会继续执行;而if会直接唤醒wait()方法,继续往下执行,不管被notify或notifyAll唤醒的是不是它,而极有可能,此时并不满足if的判断条件,就是JDK文档中所谓的“虚假唤醒”。
            synchronized (Demo.class){while(!执行条件) {obj.wait();}....if(!执行条件) {obj.wait();}obj.wait();}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/501497.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何在jieba分词中加自定义词典_Pyspark Word2Vec + jieba 训练词向量流程

摘要:用商品描述为语料库训练商品词向量为例,分享一下用pyspark自带word2vecjieba分词训练词向量的流程.工具:python,pyspark,jieba,pandas,numpy数据格式:自定义词典,语料库均为pyspark dataframe,停用辞典不大,直接使用txt.1 create spark我的pyspark参数设置如下:def create…

linux底行模式显示信息,14天linux命令加强

linux命令加强linux命令加强.jpg复习cd./ 当前目录../ 上级目录/ 代表根目录 or 代表目录和文件之间的分隔符 ..pwd 查看当前路径LS 查看当前目录下的文件ls ./a/ 查看目标路径下的文件tab 自动补全grep 文件外部根据关键字搜索文件内容 grep -n 关键字 *(文件名)more 以分页的…

AndroidManifest.xml详解

我们在进行APP开发的时候都会遇到一个文件&#xff1a;AndroidManifest.xml。从刚开始进行Android开发&#xff0c;到现在已经过去了几个月&#xff0c;还是对这个文件一知半解&#xff0c;只知道它是配置用的。但是这文件里的东西具体有什么用&#xff0c;该怎么用一直都没有理…

a标签传值到另一个页面_vue-router页面传值及接收值

前端写页面&#xff0c;我们经常需要从A页面传值给B页面&#xff0c;比如下面的场景点击“充值中”跳转到下一个页面&#xff0c;使tabbar中的页面与其对应需要上个页面传值下面来实现下&#xff1a;A页面——My.vue在去“order”页面的方法中通过params传值current1<B页面—…

如何实现文件互拖-VMware Tools (ubuntu系统)安装详细过程与使用

VMware Tools &#xff08;ubuntu系统&#xff09;安装详细过程与使用 1、打开虚拟机VMware Workstation&#xff0c;启动Ubuntu系统&#xff0c;菜单栏 - 虚拟机 - 安装VMware Tools&#xff0c;不启动Ubuntu系统是无法点击“安装VMware Tools”选项的&#xff0c;如下图&…

c++ 中文乱码_Visual Studio Code 中 CodeRunner 插件的输出窗口中文乱码

原来我一直用 Pycharm 写代码&#xff0c;Pycharm 写代码虽然很方便&#xff0c;但是Pycharm 有点重&#xff0c;我转到了Vscode了&#xff0c;真香。在 Visual Studio Code 中安装 CodeRunner 插件后&#xff0c;直接运行 Python 代码的时候&#xff0c;输出窗口中的中文出现了…

解决为什么导入了tomcat进入myeclipse却在server中找不到

有时候在servers中找不到刚刚在preferences搜索框中&#xff0c;输入tomcat等等等一系列的操作后却还是找不到在哪里 其实需要在servers窗口中右键new一个新的tomcat出来&#xff0c;这时候再在里面选择刚刚新建的tomcat即可

三菱modbusRTU通讯实例_实例 | 三菱PLC接线图干货,FX5U模块硬件

点击箭头处“工业之家”&#xff0c;选择“关注公众号”&#xff01;三菱PLC接线图干货此次主要描述的是关于三菱FX5U 模块硬件的接线实例&#xff0c;主要有以下几个方面&#xff1a;电源AC、DC接线、输入输出接线、模拟量接线。不同原理不同的接线方式&#xff0c;现在来给大…

linux共享文件系统sy,Linux使用Samba实现文件共享

Samba服务是现在Linux系统与Windows系统之间共享文件的最佳选择。[rootstudy ~]# yum install samba -y  #安装samba服务[rootstudy ~]# cat -n /etc/samba/smb.conf  #查看samba主配置文件Samba服务程序中的参数以及作用[global]参数作用workgroup MYGROUP#工作组名称ser…

recycleviewitem 列表加载动画_用vue实现一个虚拟列表

上次分享了超长列表分片加载的方式&#xff0c;这种方式现在一般不会使用&#xff0c;因为dom会变的无比庞大&#xff0c;页面会很卡&#xff0c;今天分享用vue实现一个虚拟列表的简易实现&#xff0c;本来是想用原生实现一个&#xff0c;后来觉得直接使用computed&#xff0c;…

解决为什么JDK要带着JRE一起下载

相信在安装的过程中会遇到这么一个疑问&#xff0c;明明我安装的的是JDK&#xff0c;为什么下载完成后路径里面多了一个jre呢&#xff1f; 带着这个疑问&#xff0c;我们探究一下JDK和JRE的区别 JDK&#xff1a;它是Java开发运行环境&#xff0c;在程序员的电脑上当然要安装J…

linux 安装jdk gz文件,Linux 安装jdk gz 安装方式

Linux安装JDK步骤1、先从网上下载jdk(jdk-7u1-linux-i586.rpm)&#xff0c;下载地址:http://www.Oracle.com/technetwork/Java/javase/downloads/jdk-7u1-download-513651.html&#xff0c;下载后放在/home目录中&#xff0c;当然其它地方也行。2、进入安装目录#cd /home#cp jd…

多元相关性分析_研究 | 精神分裂症症状与超氧化物歧化酶相关性的性别差异

精神分裂症是一种精神病综合征&#xff0c;主要症状包括阳性症状(如幻觉、妄想以及言语混乱)&#xff0c;阴性症状(如积极性降低、表达能力下降)&#xff0c;认知缺陷(如执行功能、记忆能力和心理处理速度受损)。氧化应激过度、抗氧化防御系统失调被认为是精神分裂症的重要危险…

安装Android studio打不开,提示the environment variable HAVA_HOME does not point to a val

遇到问题先仔细看错误提示&#xff0c;这里的意思有提到JAVA_HOME&#xff0c;因此需要我们打开一下系统的环境变量 1.java_home里面只有一个值&#xff0c;但在后面加了分号&#xff1a; 运行Java程序的时候不会报错。但是Android studio会认为不是一个正确的地址。 2.盘符问…

获取显示器的唯一编号_宝马奔驰才配拥有的HUD抬头显示器,买菜车也能无损安装!...

其实现在许多中高端车(壕车)已经开始标配或者可以选配抬头显示器&#xff0c;比如宝马现在全系好像都可以选配&#xff0c;我朋友有一台X3就带HUD&#xff0c;听说选配HUD时追加了1.3万。那HUD有什么作用呢&#xff1f;没用过的人可能会说装X大于实用&#xff0c;其实真正用过H…

g100显卡 linux驱动,nvidia geforce g100驱动

这是nvidia geforce g100驱动下载&#xff0c;一款可以有效解决NVIDIA GeForce G100显卡在使用过程中出现的一些问题的驱动工具&#xff0c;本站提供了NVIDIA GeForce G100显卡驱动的下载地址&#xff0c;有兴趣的朋友们可以前来下载使用。软件说明1、支持GeForce GTS 240、GT …

eclipse 64位_如何安装调试 Java开发工具Eclipse和JDK环境

JRE是个运行环境&#xff0c;JDK是个开发环境。因此写Java程序的时候需要JDK&#xff0c;而运行Java程序的时候就需要JRE。而JDK里面已经包含了JRE&#xff0c;因此只要安装了JDK&#xff0c;就可以编辑Java程序&#xff0c;也可以正常运行Java程序。但由于JDK包含了许多与运行…

计算机操作系统超全详解

操作系统详解 一 为什么要有操作系统 &#xff08;两本书&#xff1a;现代操作系统、操作系统原理&#xff0c;学好python以后再去研究吧~~&#xff09; 现代的计算机系统主要是由一个或者多个处理器&#xff0c;主存&#xff0c;硬盘&#xff0c;键盘&#xff0c;鼠标&#…

python画指数函数图像_python实现画出e指数函数的图像

这里用Python逼近函数y exp(x);同样使用泰勒函数去逼近: exp(x) 1 x (x)^2/(2!) .. (x)^n/(n!) ... #!/usr/bin/python # -*- coding:utf-8 -*- import numpy as np import math import matplotlib as mpl import matplotlib.pyplot as plt def calc_e_small(x): n 10 …

python怎么写入到文件中_Python学习笔记之将数据写入到文件中

原博文 2019-10-29 16:04 − 10-3 访客&#xff1a;编写一个程序&#xff0c;提示用户输入其名字&#xff1b;用户作出响应后&#xff0c;将其名字写入到文件guest.txt 中。 编写Python代码&#xff1a; 1 username input("Please enter your name: ") 2 filename …