详解Java的线程状态

Java的每个线程都具有自己的状态,Thread类中成员变量threadStatus存储了线程的状态:

private volatile int threadStatus = 0;

在Thread类中也定义了状态的枚举,共六种,如下:

public enum State {
    NEW,			//	新建状态
    RUNNABLE,		//	执行状态
    BLOCKED,		//	阻塞状态
    WAITING,		//	无限期等待状态
    TIMED_WAITING,  //  有限期等待状态
    TERMINATED;     //  退出状态
}

threadStatus初始值为0,对应的就是NEW状态。

  • NEW:新建状态,new Thread()时处于这个状态,此时线程还未开始执行
  • RUNNABLE:执行状态,当调用了start方法后,线程处于此状态,当然此刻CPU不一定正在执行它
  • BLOCKED:阻塞状态,线程等待锁时处于此状态
  • WAITING:无限期等待状态,需要被唤醒的等待属于此状态,如Object.wait
  • TIMED_WAITING:有限期等待状态,调用一些有超时时间的等待方法会进入此状态,如Thread.sleep、Object.wait、Thread.join、Lock.tryLock、Condition.await
  • TERMINATED:退出状态,可能是正常运行完毕,也可能是抛出了异常导致线程终止

我们可以通过getState获取线程的状态:

State state = thread.getState();

接下来,我们通过示例来感受线程状态的变化。

示例一:

Thread t = new Thread(() -> {
    System.out.println("sleep");
    //	休眠2秒
    ThreadUtil.sleep(2000);
    System.out.println("run");
});

//	启动前先打印一下线程状态
System.out.println(t.getState());
//	启动线程
t.start();
//	启动后立即打印一次线程状态
System.out.println(t.getState());

//	每隔500毫秒打印一次线程状态
while (true) {
    ThreadUtil.sleep(500);
    System.out.println(t.getState());
}

输出:

NEW
RUNNABLE
sleep
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
run
TERMINATED
TERMINATED
TERMINATED
TERMINATED
TERMINATED
TERMINATED
TERMINATED

可以看出,线程创建后,初始状态为NEW;

调用start方法后状态变更为了RUNNABLE;

当线程内执行了sleep,休眠2秒钟,状态变更为了TIMED_WAITING;

当线程执行完成后,状态变更为了TERMINATED。

示例二:

本示例演示在多线程争抢锁的情况下,线程状态的变化。

private static Object lock = new Object();

public static void main(String[] args) {
    Runnable runnable = () -> {
        //	加锁
        synchronized (lock) {
            System.out.println(Thread.currentThread().getName() + " lock");
            ThreadUtil.sleep(2000);
        }
        System.out.println(Thread.currentThread().getName() + " exit");
    };

    Thread t1 = new Thread(runnable, "t1");
    Thread t2 = new Thread(runnable, "t2");

    t1.start();
    t2.start();

    while (true) {
        ThreadUtil.sleep(500);
        System.out.println(t1.getName() + ":" + t1.getState());
        System.out.println(t2.getName() + ":" + t2.getState());
    }
}

输出:

t1 lock                t1获得了锁
t1:TIMED_WAITING    t1 sleep,进入有限等待状态
t2:BLOCKED          t2未获得锁,因此进入阻塞状态
t1:TIMED_WAITING    
t2:BLOCKED
t1:TIMED_WAITING
t2:BLOCKED
t1 exit             t1释放锁,执行完成,退出
t2 lock             t2获得锁
t1:TERMINATED       t1已经是退出状态
t2:TIMED_WAITING    t2 sleep,进入有限等待状态
t1:TERMINATED       
t2:TIMED_WAITING
t1:TERMINATED
t2:TIMED_WAITING
t1:TERMINATED
t2:TIMED_WAITING
t2 exit            t2释放锁,执行完成,退出
t1:TERMINATED      t1为退出状态
t2:TERMINATED      t2为退出状态

示例三:

本示例演示了线程如何进入和退出WAITING状态。

private static Object obj = new Object();

public static void main(String[] args) {
    Runnable runnable = () -> {
        synchronized (obj) {
            try {
                //	等待
                obj.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("exit");
        }
    };

    Thread t1 = new Thread(runnable, "t1");
    System.out.println(t1.getName() + ":" + t1.getState());
    t1.start();
    System.out.println(t1.getName() + ":" + t1.getState());

    for (int i = 0; i < 20; i++) {
        ThreadUtil.sleep(500);
        if(i == 3) {
            synchronized (obj) {
                //	唤醒
                obj.notify();
            }
        }
        System.out.println(t1.getName() + ":" + t1.getState());
    }
}

输出:

t1:NEW
t1:RUNNABLE
t1:WAITING    调用了obj.wait()进入无限等待状态
t1:WAITING
t1:WAITING
t1:BLOCKED  主线程获得锁,进行notify,t1进入了阻塞状态
exit               t1线程退出同步块,执行完成
t1:TERMINATED  t1线程退出
t1:TERMINATED

Java Thread的threadStatus字段值的更新代码位于hotspot c++源码中,JDK源码中看不到。

Java的线程状态并非是操作系统的实际线程状态,但与操作系统的线程状态是有对应关系的,后续有需要深入分析操作系统原理、hotspot源码再展开。

到此这篇关于详解Java的线程状态的文章就介绍到这了,更多相关Java线程状态内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java 解析线程的几种状态详解

    目录 1.线程的5种状态 2.Java线程的6种状态 3.Java线程状态的转换 总结 1. 线程的5种状态 从操作系统层面上,任何线程一般都具有五种状态,即创建.就绪.运行.阻塞.终止. (1) 新建状态(NEW) 在程序中用构造方法创建一个新线程时,如new Thread(),该线程就是创建状态,此时它已经有了相应的内存空间和其它资源,但是还没有开始执行. (2) 就绪状态(READ) 新建线程对象后,调用该线程的start()方法就可以启动线程.当线程启动时,线程就进入就绪状态(runna

  • 简单谈谈Java 中的线程的几种状态

    Java 中的线程有以下状态: 新建状态(New):新创建的线程,还未执行. 就绪状态(Runnable):执行了 start() 方法,等待运行, 运行状态(Running):就绪状态的线程开始执行程序代码. 阻塞状态(Blocked) 同步堵塞:在运行过程中,需要拿到锁才能运行,而锁被其他资源占用,需要等待. 等待堵塞:执行了 wait() 方法,进入了等待. 其他堵塞:执行了 join().sleep() 方法,进入了等待. 终止状态(Terminated):运行完 run() 方法后结束

  • 深入探究Java线程的状态与生命周期

    目录 一.线程的状态 新建(初始) 就绪(可运行) 运行 阻塞 死亡 二.线程的状态转移 三.线程的生命周期 一.线程的状态 NEW: 安排了工作, 还未开始行动RUNNABLE: 可工作的. 又可以分成正在工作中和即将开始工作.BLOCKED: 这几个都表示排队等着其他事情WAITING: 这几个都表示排队等着其他事情TIMED_WAITING: 这几个都表示排队等着其他事情TERMINATED: 工作完成了 新建(初始) 当继承Thread类和实现了Runnable接口,就可以创建线程,新建

  • Java线程的五种状态介绍

    目录 1. 线程的5种状态 2. Java线程的6种状态 3. Java线程状态的转换 1. 线程的5种状态 从操作系统层面上,任何线程一般都具有五种状态,即创建.就绪.运行.阻塞.终止. (1) 新建状态(NEW) 在程序中用构造方法创建一个新线程时,如new Thread(),该线程就是创建状态,此时它已经有了相应的内存空间和其它资源,但是还没有开始执行. (2) 就绪状态(READ) 新建线程对象后,调用该线程的start()方法就可以启动线程.当线程启动时,线程就进入就绪状态(runna

  • Java并发编程之线程状态介绍

    目录 线程状态概述 睡眠sleep方法 等待和唤醒 等待唤醒的一个小例子 线程状态概述 线程由生到死的完整过程: 当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态.在线程的生命周期中,有几种状态呢?在API中java.lang.Thread.State这个枚举中给出了六种线程状态: 线程状态 导致状态发生条件 NEW(新建) 线程刚被创建,但是并未启动.还没调用start方法.MyThread t = new MyThread只有线程对象,没有线程特征. Runna

  • 详解Java的线程状态

    Java的每个线程都具有自己的状态,Thread类中成员变量threadStatus存储了线程的状态: private volatile int threadStatus = 0; 在Thread类中也定义了状态的枚举,共六种,如下: public enum State { NEW, // 新建状态 RUNNABLE, // 执行状态 BLOCKED, // 阻塞状态 WAITING, // 无限期等待状态 TIMED_WAITING, // 有限期等待状态 TERMINATED; // 退出状

  • 详解Java停止线程的四种方法

    一.线程停止基础知识 interrupted(): 测试当前线程是否已经中断.该方法为静态方法,调用后会返回boolean值.不过调用之后会改变线程的状态,如果是中断状态调用的,调用之后会清除线程的中断状态. isInterrupted(): 测试线程是否已经中断.该方法由对象调用 interrupt(): 标记线程为中断状态,不过不会中断正在运行的线程. stop(): 暴力停止线程.已弃用. 二.停止线程方法1:异常法停止 线程调用interrupt()方法后,在线程的run方法中判断当前对

  • 详解Java创建线程的五种常见方式

    目录 Java中如何创建线程呢? 1.显示继承Thread,重写run来指定现成的执行代码. 2.匿名内部类继承Thread,重写run来执行线程执行的代码. 3.显示实现Runnable接口,重写run方法. 4.匿名内部类实现Runnable接口,重写run方法 5.通过lambda表达式来描述线程执行的代码 [面试题]:Thread的run和start之间的区别? Thread类的具体用法 Thread类常见的一些属性 中断一个线程 1.方法一:让线程run完 2.方法二:调用interr

  • 详解JAVA 设计模式之状态模式

    在状态模式(State Pattern)中,类的行为是基于它的状态改变的.这种类型的设计模式属于行为型模式. 在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context 对象. 介绍 意图: 允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类. 主要解决: 对象的行为依赖于它的状态(属性),并且可以根据它的状态改变而改变它的相关行为. 何时使用: 代码中包含大量与对象状态有关的条件语句. 如何解决: 将各种具体的状态类抽象出来. 关键代码: 通常

  • 详解Java子线程异常时主线程事务如何回滚

    一.提出问题 最近有一位朋友问了我这样一个问题,问题的截图如下: 这个问题问的相对比较笼统,我来稍微详细的描述下:主线程向线程池提交了一个任务,如果执行这个任务过程中发生了异常,如何让主线程捕获到该异常并且进行事务的回滚. 二.主线程与子线程 先来看看基础,下图体现了两种线程的运行方式, 左侧的图,体现了主线程启动一个子线程之后,二者互不干扰独立运行,生死有命,从此你我是路人! 右侧的图,体现了主线程启动一个子线程之后继续执行主线程程序逻辑,在某一节点通过阻塞的方式来获取子线程的执行结果. 对于

  • 详解Java同步—线程锁和条件对象

    线程锁和条件对象 在大多数多线程应用中,都是两个及以上线程需要共享对同一数据的存取,所以有可能出现两个线程同时访问同一个资源的情况,这种情况叫做:竞争条件. 在Java中为了解决并发的数据访问问题,一般使用锁这个概念来解决. 有几种机制防止代码收到并发访问的干扰: 1.synchronized关键字(自动创建一个锁及相关的条件) 2.ReentrantLock类+Java.util.concurrent包中的lock接口(在Java5.0的时候引入) ReentrantLock的使用 publi

  • 详解Java的线程的优先级以及死锁

    Java线程优先级 需要避免的与多任务处理有关的特殊错误类型是死锁(deadlock).死锁发生在当两个线程对一对同步对象有循环依赖关系时.例如,假定一个线程进入了对象X的管程而另一个线程进入了对象Y的管程.如果X的线程试图调用Y的同步方法,它将像预料的一样被锁定.而Y的线程同样希望调用X的一些同步方法,线程永远等待,因为为到达X,必须释放自己的Y的锁定以使第一个线程可以完成.死锁是很难调试的错误,因为: 通常,它极少发生,只有到两线程的时间段刚好符合时才能发生. 它可能包含多于两个的线程和同步

  • Java多线程 线程状态原理详解

    这篇文章主要介绍了Java多线程 线程状态原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 java.lang.Thread.State枚举定义了6种线程状态. NEW: 尚未启动(start)的线程的线程状态 RUNNABLE: 运行状态,但线程可能正在JVM中执行,也可能在等待CPU调度 BLOCKED: 线程阻塞,等待监视器锁以进入同步代码块/方法 WAITING: 等待状态.使用以下不带超时的方式时会进入:Object.wait.

  • 详解JAVA 线程-线程的状态有哪些?它是如何工作的?

    线程(Thread)是并发编程的基础,也是程序执行的最小单元,它依托进程而存在. 一个进程中可以包含多个线程,多线程可以共享一块内存空间和一组系统资源,因此线程之间的切换更加节省资源.更加轻量化,也因此被称为轻量级的进程. 线程的状态在 JDK 1.5 之后以枚举的方式被定义在 Thread 的源码中,它总共包含以下 6 个状态: NEW,新建状态,线程被创建出来,但尚未启动时的线程状态: RUNNABLE,就绪状态,表示可以运行的线程状态,它可能正在运行,或者是在排队等待操作系统给它分配 CP

  • 一文详解Java线程的6种状态与生命周期

    目录 1.线程状态(生命周期) 2.操作线程状态 2.1.新创建状态(NEW) 2.2.可运行状态(RUNNABLE) 2.3.被阻塞状态(BLOCKED) 2.4.等待唤醒状态(WAITING) 2.5.计时等待状态(TIMED_WAITING) 2.6.终止(TERMINATED) 3.查看线程的6种状态 1.线程状态(生命周期) 一个线程在给定的时间点只能处于一种状态. 线程可以有如下6 种状态: New (新创建):未启动的线程: Runnable (可运行):可运行的线程,需要等待操作

随机推荐