线程与操作系统中线程(进程)的概念同根同源,尽管千差万别。
操作系统中有状态以及状态的切换,Java线程中照样也有。

State

在Thread类中有内部类 枚举State,用于抽象描述Java线程的状态,共有6种不同的状态
详细定义如下:

public enum State {

/**

* 至今尚未启动的线程的状态。

*/

NEW,

/**

* 可运行线程的线程状态。

* 处于可运行状态的某一线程正在 Java 虚拟机中运行,但它可能正在等待操作系统中的其他资源,比如处理器。

*/

RUNNABLE,

/**

* 受阻塞并且正在等待监视器锁的某一线程的线程状态。

* 处于受阻塞状态的某一线程正在等待进入一个同步的块/方法的监视器锁,或者在调用 Object.wait 之后再次进入同步的块/方法。

*/

BLOCKED,

/**

* 某一等待线程的线程状态。

* 某一线程因为调用下列方法之一而处于等待状态:

* 不带超时值的 Object.wait

* 不带超时值的 Thread.join

* LockSupport.park

* 处于等待状态的线程正等待另一个线程,以执行特定操作。

* 例如,已经在某一对象上调用了 Object.wait() 的线程正等待另一个线程,以便在该对象上调用 Object.notify() 或 Object.notifyAll()。

* 已经调用了 Thread.join() 的线程正在等待指定线程终止。

*/

WAITING,

/**

* 具有指定等待时间的某一等待线程的线程状态。

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

* Thread.sleep

* 带有超时值的 Object.wait

* 带有超时值的 Thread.join

* LockSupport.parkNanos

* LockSupport.parkUntil

*/

TIMED_WAITING,

/**

* 已终止线程的线程状态。线程已经结束执行。

*/

TERMINATED;

}

状态详解
 

NEW

当一个线程创建后,也就是new了一个Thread,那么这个Thread的state就是NEW
有且只有这种情况下,才为NEW,不会从任何状态转换而来
也就是说如果一个线程状态已经不再是NEW,那么他永远不可能再重新回到NEW的状态,这是一个起点
 
下面的示例中创建了一个线程myThread,并没有调用start方法

TERMINATED

当一个线程终止后,就进入状态TERMINATED
TERMINATED作为线程的终点,一旦进入TERMINATED状态,将不再能够转换为其他状态
 
下面的示例中,创建了一个线程myThread,并且调用start方法启动
然后主线程(当前线程)sleep 1秒(确保myThread肯定结束了),然后查看myThread的状态,很显然,此时已经进入终止状态
 
NEW和TERMINATED分别对应线程生命周期的起点和终点
对于NEW来说,一旦离开,就永远回不来了;
对于TERMINATED来说,一旦到达, 就永远回不去了;

RUNNABLE

RUNNABLE用于表示可运行状态
下面的代码在主线程中运行,运行过程中是RUNNABLE状态
API中有说到:“处于可运行状态的某一线程正在 Java 虚拟机中运行,但它可能正在等待操作系统中的其他资源,比如处理器。”
也就是说一个RUNNABLE并不是一定正在运行
如果我们将线程运行所有的资源与条件分为两种:CPU时间片以及除了时间片以外的所有其他;
一旦进入RUNNABLE状态,那么他肯定已经拥有了“除了时间片以外的所有其他资源”
 但是,是否正在被执行?这个不确定,还要看是否被分配了时间片
如果没有处理器资源(时间片)那么就是“准备妥当”状态,如果分配了处理器资源(时间片),那么就是“正在运行”状态。
所以RUNNABLE状态可以细分为两种状态:准备妥当(READY)RUNNING(正在运行)
但是,为什么没有将RUNNABLE细分?
很显然,对于开发者来说能够做到的就是“除了时间片以外的所有其他资源”,而对于操作系统处理器CPU时间片的调度,是完全没有能力操控的(yield也只是提示)
所以,从应用的角度看,也就只有RUNNABLE状态,一个RUNNABLE的线程,他随时可能在运行,也可能在等待调度。

等待状态

BLOCKED、WAITING、TIMED_WAITING三种状态相对前面的几种,相对稍微复杂一点,因为会涉及到各种切换
对照着汉字来说,这三者都有“等”的意思,但是却又不太相同
举几个例子感受一下
当你发现前方信号灯转变为红灯时,你停车等待;
当你经过斑马线时,正好有行人经过,你停车等待;
当售票窗口中午休息时,你原地等待;
这几种等待更多的是因为不可抗力,不得不等的一种场景,BLOCKED更接近这种等待;
对于临界资源的访问,需要互斥访问,Java中使用对象监视器作为锁,想要进入同步区域,就需要获得对应的监视器锁
如果获取不到,就需要等待,这就是BLOCKED状态;
 
要出门时,你老婆说我化个妆,你等我下;
买水果时,售货员说刚卖完了,师傅去仓库去取了,您稍等一下;
此时的等,是在等一件事情的发生,WAITING更接近这种等待;
虽然都是在等待,卡住不能动,还是等一等,还是有区别的;
TIMED_WAITING与WAITING就比较相似了,他们的区别,从汉语的角度理解类似“你等我两分钟和你等一会”的区别
等两分钟有时间,等一会儿不确定到底等待多大一会儿
再回到Java线程中,可以认为:
  • 如果一个线程在等待获取进入同步区域的监视器锁,那么是BLOCKED;
  • 如果线程调用了不带超时值的等待方法,比如 Object.wait,持续等待某件事情的发生,直到收到通知,那么是WAITING
  • 如果线程调用了比如带有超时值的等待方法,比如wait(long timeout),进行一定时间的等待,到到时间后将不再等待,那么是TIMED_WAITING

状态转换图

 
换一个角度理解,线程状态的切换
下图从前驱和后继的角度分析了线程状态的变化
以中间一列为中心

状态对比

既然操作系统中线程概念模型有状态切换,Java线程也有状态,他们有何异同?
如上图所示,操作系统中的进程、线程模型的状态
核心为就绪(ready)阻塞(waiting)执行(run)
而对于Java线程中
核心状态为RUNNABLE、BLOCKED、WAITING、TIMED_WAITING(项目中根本不会创建线程,会借助于线程池,所以NEW和TERMINATED非重点)
Java线程为操作系统原生线程的映射,状态上也是有所映射的
Runnable状态,则对应了操作系统中的就绪(ready)和执行(run)
TIMED_WAITING ,WAITING还是BLOCKED,对应的都是操作系统线程的阻塞(waiting)状态
需要注意的是:这些状态是虚拟机状态,它不反映任何操作系统的线程状态,可以查看State的注释

为什么状态没有对应?

我们之前在提及线程的实现时,就有说到用户级和内核支持的对比,内核支持的是依靠操作系统来调度的,1.2之后就是对操作系统线程的映射
所以,既然调度依赖的是操作系统,那么,操作系统底层的状态对于开发者来说就不是那么必要了,因为你并不能对他进行事无巨细的控制
JVM中的线程是操作系统底层线程的映射,既然是映射,可以认为是一个薄层封装
封装的目的是为了更好的符合Java多线程编程的模型,而不是要原模原样的去照搬
从这一点也能更好地理解,为什么RUNNABLE相当于READY和RUNNING,因为JVM本来就只能做到这一步,READY还是RUNNING,搞不了,那还提供这两个状态干什么呢?
所以记住:
JVM中的状态只是Java的多线程模型中的状态,并不反应任何操作系统的线程状态
JVM中的状态与底层操作系统中线程的状态也没有必要去映射

Java线程Thread的状态解析以及状态转换分析 多线程中篇(七)的更多相关文章

  1. Java内存模型JMM 高并发原子性可见性有序性简介 多线程中篇(十)

    JVM运行时内存结构回顾 在JVM相关的介绍中,有说到JAVA运行时的内存结构,简单回顾下 整体结构如下图所示,大致分为五大块 而对于方法区中的数据,是属于所有线程共享的数据结构 而对于虚拟机栈中数据 ...

  2. Java线程的周期及五种状态

    线程的生命周期及五种基本状态 关于Java中线程的生命周期,首先看一下下面这张较为经典的图: 上图中基本上囊括了Java中多线程各重要知识点.掌握了上图中的各知识点,Java中的多线程也就基本上掌握了 ...

  3. Java线程池源码解析

    线程池 假如没有线程池,当存在较多的并发任务的时候,每执行一次任务,系统就要创建一个线程,任务完成后进行销毁,一旦并发任务过多,频繁的创建和销毁线程将会大大降低系统的效率.线程池能够对线程进行统一的分 ...

  4. java 线程 Thread 使用介绍,包含wait(),notifyAll() 等函数使用介绍

    (原创,转载请说明出处!谢谢--http://www.cnblogs.com/linguanh/) 此文目的为了帮助大家较全面.通俗地了解线程 Thread 相关基础知识! 目录: --线程的创建: ...

  5. Java 线程池(ThreadPoolExecutor)原理解析

    在我们的开发中“池”的概念并不罕见,有数据库连接池.线程池.对象池.常量池等等.下面我们主要针对线程池来一步一步揭开线程池的面纱. 有关java线程技术文章还可以推荐阅读:<关于java多线程w ...

  6. TCP协议 状态解析和状态统计

    一.三次握手和四次挥手 1.建立连接(三次握手)   (1)服务器会处于listen状态,客户端发送一个带SYN标志的TCP报文到服务器.   (2)服务器端回应客户端的请求,这是三次握手中的第2个报 ...

  7. Java并发编程:Java线程池核心ThreadPoolExecutor的使用和原理分析

    目录 引出线程池 Executor框架 ThreadPoolExecutor详解 构造函数 重要的变量 线程池执行流程 任务队列workQueue 任务拒绝策略 线程池的关闭 ThreadPoolEx ...

  8. java 线程Thread 技术--线程状态与同步问题

    线程技术第三篇: 线程的状态: 1. 创建状态: 当用new 操作符创建一个新的线程对象时,该线程就处于创建状态,系统不为它分配资源 2.可运行状态:当线程调用start 方法将为线程分配必须的系统资 ...

  9. java 线程Thread 技术--volatile关键字

    java 语言中允许线程访问共享变量,为了保证共享变量能被准确和一致的更新,Java 语言提供了volatile 关键字,也就是我们所说的内存一致性: 问题抛出:(尝试去运行下面代码,以及将volat ...

随机推荐

  1. SpringMVC之拦截器的的配置和使用

    拦截器与过滤器的区别:拦截器只能拦截controller的请求,过滤器可以过滤所有请求 (1)实现HandlerInterceptor接口 在执行控制器中的方法之前执行preHandle()中的方法 ...

  2. 微信小程序开发----微信开发者工具使用

    新建项目选择小程序项目,选择代码存放的硬盘路径,填入刚刚申请到的小程序的 AppID,给你的项目起一个好听的名字,最后,勾选 "创建 QuickStart 项目" (注意: 你要选 ...

  3. 浅谈微信小程序一二

    1.生命周期 1.onLoad():页面加载时触发,一个页面只加载一次. 2.onShow():页面显示切换的时候触发 3.onReady():页面初次渲染完成时触发.一个页面只会调用一次,代表页面已 ...

  4. Spring源码阅读 源码环境搭建(一)

    ring 源码阅读的搭建(一) 一 下载spring源码 进入官方网页:https://spring.io/projects/spring-framework 进入相关的github位置,下载zip包 ...

  5. FCC(ES6写法) Friendly Date Ranges

    把常见的日期格式如:YYYY-MM-DD 转换成一种更易读的格式. 易读格式应该是用月份名称代替月份数字,用序数词代替数字来表示天 (1st 代替 1). 包含当前年份和相同月份的时候,makeFri ...

  6. Java软件工程师面试常见问题集锦之一

    1.面向对象的特征有哪些方面 1.抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面.抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节.抽象 ...

  7. [Bash]LeetCode192. 统计词频 | Word Frequency

    Write a bash script to calculate the frequency of each word in a text file words.txt. For simplicity ...

  8. [Swift]LeetCode399. 除法求值 | Evaluate Division

    Equations are given in the format A / B = k, where A and B are variables represented as strings, and ...

  9. [Swift]LeetCode404. 左叶子之和 | Sum of Left Leaves

    Find the sum of all left leaves in a given binary tree. Example: 3 / \ 9 20 / \ 15 7 There are two l ...

  10. awk小例子_2_数值统计脚本

    通信公司工作,经常处理各种协议接口,在统计协议接口字段内容时,需要统计字段填写的内容是否正确,和占比是多少.要是单次统计,估计会把人累死,写个脚本统计,轻松便捷. 举例:接口内容 这是一条话单,这样的 ...