前文传送门:多线程概述及创建方式

Java:线程的六种状态及转化

关于线程的生命周期,网上书上说法不一,难以统一,本篇做一个总结:

java.lang.Thread.State枚举类中定义了六种线程的状态,可以调用线程Thread中的getState()方法获取当前线程的状态

线程状态 解释
NEW 尚未启动的线程状态,即线程创建,还未调用start方法
RUNNABLE 就绪状态(调用start,等待调度)+正在运行
BLOCKED 等待监视器锁时,陷入阻塞状态
WAITING 等待状态的线程正在等待另一线程执行特定的操作(如notify)
TIMED_WAITING 具有指定等待时间的等待状态
TERMINATED 线程完成执行,终止状态

下图源自《Java并发编程艺术》图4-1

一、新建状态(NEW)

即用new关键字新建一个线程,这个线程就处于新建状态

二、运行状态(RUNNABLE)

操作系统中的就绪和运行两种状态,在Java中统称为RUNNABLE。

就绪状态(READY)

当线程对象调用了start()方法之后,线程处于就绪状态,就绪意味着该线程可以执行,但具体啥时候执行将取决于JVM里线程调度器的调度。

It is never legal to start a thread more than once. In particular, a thread may not be restarted once it has completed execution.

  • 不允许对一个线程多次使用start。

  • 线程执行完成之后,不能试图用start将其唤醒。

其他状态 ->就绪

  • 线程调用start(),新建状态转化为就绪状态。
  • 线程sleep(long)时间到,等待状态转化为就绪状态。
  • 阻塞式IO操作结果返回,线程变为就绪状态。
  • 其他线程调用join()方法,结束之后转化为就绪状态。
  • 线程对象拿到对象锁之后,也会进入就绪状态。

运行状态(RUNNING)

处于就绪状态的线程获得了CPU之后,真正开始执行run()方法的线程执行体时,意味着该线程就已经处于运行状态。需要注意的是,对于单处理器,一个时刻只能有一个线程处于运行状态。
对于抢占式策略的系统来说,系统会给每个线程一小段时间处理各自的任务。时间用完之后,系统负责夺回线程占用的资源。下一段时间里,系统会根据一定规则,再次进行调度。

运行状态转变为就绪状态的情形:

  • 线程失去处理器资源。线程不一定完整执行的,执行到一半,说不定就被别的线程抢走了。
  • 调用yield()静态方法,暂时暂停当前线程,让系统的线程调度器重新调度一次,它自己完全有可能再次运行。

yield方法的官方解释:

A hint to the scheduler that the current thread is willing to yield its current use of a processor. The scheduler is free to ignore this hint.

提示调度程序,当前线程愿意放弃当前对处理器的使用。这时,当前线程将会被置为就绪状态,和其他线程一样等待调度,这时候根据不同优先级决定的概率,当前线程完全有可能再次抢到处理器资源。

三、阻塞状态(BLOCKED)

阻塞状态表示线程正等待监视器锁,而陷入的状态。

以下场景线程将会阻塞:

  • 线程等待进入synchronized同步方法。
  • 线程等待进入synchronized同步代码块。

线程取得锁,就会从阻塞状态转变为就绪状态。

四、等待状态(WAITING)

进入该状态表示当前线程需要等待其他线程做出一些的特定的动作(通知或中断)。

运行->等待

  • 当前线程运行过程中,其他线程调用join方法,当前线程将会进入等待状态。
  • 当前线程对象调用wait()方法。
    -LockSupport.park():出于线程调度的目的禁用当前线程

等待->就绪

  • 等待的线程被其他线程对象唤醒notify()notifyAll()
  • LockSupport.unpark(Thread),与上面park方法对应,给出许可证,解除等待状态

五、超时等待状态(TIMED_WAITING)

区别于WAITING,它可以在指定的时间自行返回。

运行->超时等待

  • 调用静态方法,Thread.sleep(long)
  • 线程对象调用wait(long)方法
  • 其他线程调用指定时间的join(long)
  • LockSupport.parkNanos()
  • LockSupport.parkUntil()

补充:
sleep和yield的不同之处:

  • sleep(long)方法会使线程转入超时等待状态,时间到了之后才会转入就绪状态。而yield()方法不会将线程转入等待,而是强制线程进入就绪状态。
  • 使用sleep(long)方法需要处理异常,而yield()不用。

超时等待->就绪

  • 同样的,等待的线程被其他线程对象唤醒,notify()notifyAll()
  • LockSupport.unpark(Thread)

六、消亡状态

线程的终止,表示线程已经执行完毕。前面已经说了,已经消亡的线程不能通过start再次唤醒。

  • run()和call()线程执行体中顺利执行完毕,线程正常终止
  • 线程抛出一个没有捕获的Exception或Error。

需要注意的是:主线成和子线程互不影响,子线程并不会因为主线程结束就结束。


许多地方仍需后期补充,敬请期待。

参考资料:《JAVA并发编程实践》、《疯狂Java讲义》、《Java并发编程艺术》

Java:线程的六种状态及转化的更多相关文章

  1. Java线程的六种状态

    java线程有很多种状态,最主要的有六种,被创建.运行.睡眠.等待.阻塞以及消亡六种,也有很多归结为5种,把睡眠以及等待归结为冻结: 被创建:就是线程被创建,就是new thread()之后就是创建一 ...

  2. Java线程Thread的状态解析以及状态转换分析 多线程中篇(七)

    线程与操作系统中线程(进程)的概念同根同源,尽管千差万别. 操作系统中有状态以及状态的切换,Java线程中照样也有. State 在Thread类中有内部类 枚举State,用于抽象描述Java线程的 ...

  3. java线程五种状态

    java线程五种状态: 创建 -> 就绪 -> 运行 -> 销毁 创建 -> 就绪 -> 运行 -> 等待(缺少资源) -> 销毁 下图:各种状态转换

  4. java线程四种状态

    一个线程可以有四种状态: 1.新(new), 即线程刚刚创建,而并未执行 2.可运行(runnable),意味着一旦时间分片机制有空闲的CPU周期提供给一个线程,那个线程便可立即开始运行.因此,线程可 ...

  5. 为什么 Java 线程没有 Running 状态?

    Java虚拟机层面所暴露给我们的状态,与操作系统底层的线程状态是两个不同层面的事.具体而言,这里说的 Java 线程状态均来自于 Thread 类下的 State 这一内部枚举类中所定义的状态: 什么 ...

  6. java线程的五大状态,阻塞状态详解

    一.状态简介 一个线程的生命周期里有五大状态,分别是: 新生 就绪 运行 死亡 运行后可能遇到的阻塞状态 二.相关方法 2.1 新生状态 Thread t = new Thread(); 正如我们前面 ...

  7. JAVA线程间的状态转换

    线程间的状态转换:  1. 新建(new):新创建了一个线程对象. 2. 可运行(runnable):线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法.该状态的线程位于可运 ...

  8. Java-技术专区-如何监控Java线程池的状态

    线程池介绍 什么是线程池.线程池核心类.线程池工作流程.线程池分类.拒绝策略.及如何提交与关闭线程池等. 但在实际开发过程中,在线程池使用过程中可能会遇到各方面的故障,如线程池阻塞,无法提交新任务等. ...

  9. java线程控制、状态同步、volatile、Thread.interupt以及ConcurrentLinkedQueue

    在有些严格的系统中,我们需要做到干净的停止线程并清理相关状态.涉及到这个主题会带出很多的相关点,简单的总结如下: 我们知道,在java中,有一个volatile关键字,其官方说明(https://do ...

随机推荐

  1. Zabbix监控web

    1.1 创建主机 1.2 应用集 1.3 创建web场景 1.4 创建触发器

  2. Python学习3月8号【python编程 从入门到实践】---》笔记(1)

    第十章:处理文件和异常 #学习处理文件,让程序能够快速地分析大量的数据#学习错误处理,避免程序在面对意外情形时崩溃#学习异常,是python创建的特殊对象,用于管理程序运行时出现#学习模块json,它 ...

  3. 006一句话解决主机pc,Vmware虚拟机,开发板之间的ping问题

  4. linux solr7.2+tomcat8 详细部署整合

    1.去solr官网下solr-7.2.0.tgz 2.上传至linux解压 tar -zxvf solr-7.2.0.tgz 3.准备tomcat8 拷贝solr-7.2.0/server/solr- ...

  5. Git 连接github

    大概如下: 详细如下:如果使用本文命令,请仔细选择,因为添加一些相关命令以供参考. 1 本地仓库 1.1 创建git 仓库 git init # 初始化本地仓库 git --version # 查看G ...

  6. 1023 组个最小数 (20 分)C语言

    给定数字 0-9 各若干个.你可以以任意顺序排列这些数字,但必须全部使用.目标是使得最后得到的数尽可能小(注意 0 不能做首位).例如:给定两个 0,两个 1,三个 5,一个 8,我们得到的最小的数就 ...

  7. virtualenv虚拟环境使用及介绍

    一.为什么使用virtualenv虚拟环境 每个虚拟环境下的依赖相互独立,不同的项目可以单独使用一套python环境,减少各依赖包的影响 更容易部署 容器化 二.virtualenv创建虚拟环境 三. ...

  8. .net core 开车记:Data Protection Key 过期问题与登录页面访问慢

    K8s 船还没修好,.net core 车又出了问题,开着 k8s 豪华邮轮.飚着 .net core 极品飞车的好事真是多磨. 自从我们用上 .net core ,就一直被 .net core 的一 ...

  9. Arrays.asList 返回值类型

    public static void main(String[] args) { Integer[] datas = {1,2,3,4,5}; List<Integer> list = A ...

  10. POJ 1269 Intersecting Lines(判断两直线位置关系)

    题目传送门:POJ 1269 Intersecting Lines Description We all know that a pair of distinct points on a plane ...