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

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. 百度DMA+小度App的蓝牙语音解决方案展示

    前记   跟着百度也有一段时间了,经过一年多的努力,我们也做出了一些基于百度的语音助手的产品方案.下面就给大家秀一下我们做的产品.有类似需求的朋友可以多多交流.我们的合作方式十分灵活,可以卖芯片你自己 ...

  2. 1067 试密码 (20分)C语言

    当你试图登录某个系统却忘了密码时,系统一般只会允许你尝试有限多次,当超出允许次数时,账号就会被锁死.本题就请你实现这个小功能. 输入格式: 输入在第一行给出一个密码(长度不超过 20 的.不包含空格. ...

  3. 16.用pycharm导入自己写的模块时,import无法识别的解决办法

    我们用pycharm打开自己写的代码,当多个文件之间有相互依赖的关系的时候,import无法识别自己写的文件,但是我们写的文件又确实在同一个文件夹中, 这种问题可以用下面的方法解决: 1)打开File ...

  4. Django框架之数据库ORM框架

    首先,我来介绍一下什么是ORM框架: O是object,也就类对象的意思,R是relation,翻译成中文是关系,也就是关系数据库中数据表的意思,M是mapping,是映射的意思.在ORM框架中,它帮 ...

  5. C# 根据链接提取div内容

    安装NuGet包    HtmlAgilityPack var wc = new WebClient(); wc.Encoding = Encoding.GetEncoding("UTF-8 ...

  6. vue不常用到的v-model修饰符

    v-model的input事件同步输入框的数据根据输入的内容实时改变.v-model.lazy则是与change事件同步,即失去焦点或是回车才更新 v-model.number 将输入的数字转换为Nu ...

  7. eclipse中使用postgreSQL报错( Cannot load JDBC driver class )

    需求: 使用Maven插件调用PostgreSQL数据库 环境: eclipse_4.5.0+JDK_1.7+Tomcat_7.0+Maven+postgresql-9.1-901.jdbc4.jar ...

  8. 原生javascript 基础动画函数封装(二)

    <!DOCTYPE html> <html> <head> <title></title> <style type="tex ...

  9. python中方法调用和函数调用的区别

    函数调用: 传几个参数,就会有几个实参方法调用: 默认传递一个参数self,至少要定义一个形参

  10. dp-最大递增子段和

      Nowadays, a kind of chess game called “Super Jumping! Jumping! Jumping!” is very popular in HDU. M ...