图文详解jvm中的线程状态

article/2025/8/27 8:15:41

       本文使用下面这张图详细介绍JAVA线程的六种状态    

 



            JAVA线程的六种状态详解


               在java.lang.Thread类中,定义了线程的以下六种状态(同一个时刻线程只能有一种状态)

               NEW(新建) 这个状态是指线程刚创建,但还未调用线程的start()方法进行启动,对应上图中的New状态

               RUNNABLE(可运行) 这个状态是指线程处于正常运行中,对应上图中的Runnable与Running状态,若获得CPU时间片则处于Running状态,否则处于Runnable状态

               BLOCKED(阻塞)这个状态是指当线程进入一个被synchronized修饰的方法或语句块(也叫临界区)时,如果锁已被其他线程所获取,则会进入此状态。对应上图中的锁定Blocked状态

               WAITING(无限等待)这个状态是指当线程获取到对象锁进入临界区内,调用了锁对象的wait()方法或者thread.join()方法后进入的状态。线程进入该状态会释放锁对象,并且等待被其他的线程所唤醒,处于这种状态的线程不会被分配CPU时间片。该状态对应上图中的等待Blocked状态

              TIMED_WAITING(有限等待)  这个状态是指当线程调用了以下方法后进入的状态。在指定时间后由系统将它们自动唤醒,处于这种状态的线程不会被分配CPU时间片。该状态对应上图中的Blocked状态

              1.Thread.sleep()方法

              2.Object.wait()方法(有timeout参数)

              3.thread.join()方法(有timeout参数)

              TERMINATED(死亡) 这个状态是指run()方法已执行完毕,线程进入死亡状态

    

            JAVA线程状态切换详解

        1.NEW状态

            当我们new一个线程,但还未调用线程的start()方法时,线程为NEW状态,使用thread.getState()方法可以获取线程状态,如下这段代码:

public class Test {public static void main(String[] args) {Thread t1 = new Thread(new Task1());System.out.println(t1.getState());}
}class Task1 implements Runnable {@Overridepublic void run() {System.out.println();}
}

           程序执行结果:

           


           2.RUNNABLE状态

              当线程调用start()方法后进入该状态,对应上图中New状态向Runnable状态的转变。但是注意,这不代表线程马上就开始运行程序,此时线程需要等待CPU给它分配时间片,分配到了CPU时间片才算是真正意义上的程序执行(对应上图中Runnable状态向Running状态的转变),CPU时间片执行完毕后线程需要等待CPU下一次给它分配CPU时间片(对应上图中Running状态向Runnable状态的转变)。

              当线程获得CPU时间片并正在执行程序时,如果此时线程调用yield()方法,线程会让出当前CPU时间片,并与其他线程一起竞争下一次的CPU时间片(有可能下一次的CPU时间片还是被该线程获得)         

public class Test {public static void main(String[] args) {Thread t1 = new Thread(new Task1());t1.start();System.out.println(t1.getState());}
}class Task1 implements Runnable {@Overridepublic void run() {System.out.println();}
}

              程序执行结果:

                 


              3.BLOCKED状态

                 当线程分配到CPU时间片并在执行程序时,假如此时需要进入一个synchronized方法或语句块,但是锁对象正在被其它线程所使用,而无法获取锁进入临界区,此时线程进入entry set区,状态为BLOCKED。对应上图中由Running状态向锁定Blocked状态的转变。如下这段代码:当线程t1获取test对象锁后执行blockTest()方法,此时t2线程进入test对象的entry set区,等待t1线程释放锁后竞争锁资源,此时t2线程的状态为BLOCKED    

public class Test {public static void main(String[] args) {Test test = new Test();Thread t1 = new Thread(new Task1(test));Thread t2 = new Thread(new Task2(test));t1.start();t2.start();try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("t1:" + t1.getState());System.out.println("t2:" + t2.getState());}public void blockTest() {synchronized (this) {try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}}}
}class Task1 implements Runnable {private Test test;public Task1(Test test) {this.test = test;}@Overridepublic void run() {test.blockTest();}
}class Task2 implements Runnable {private Test test;public Task2(Test test) {this.test = test;}@Overridepublic void run() {test.blockTest();}
}    

              程序执行结果:

              


              4.WAITING状态

                  当线程在临界区内执行程序,此时如果执行的代码为对象锁的wait()方法或thread.join方法时,线程将释放锁,并且进入wait set区,等待被其它线程所唤醒,线程状态由RUNNABLE转变为WAITING(对应上图的Running状态转变为等待Blocked状态)。下面第一段代码说明线程执行临界区中锁对象的wait方法时,线程状态的变化,此时由于没有其它线程去唤醒该线程,所以该线程的状态会一直保持在waiting状态。下面第二段代码说明线程t2在执行t1.join()方法后由RUNNABLE状态转变为WAITING状态,等到t1线程的run方法执行完线程t2再执行,线程的join方法底层也是由wait()方法来实现的

                  当其它线程调用该对象的notify或notifyAll方法后,该线程被唤醒,并由wait set区进入entry set区,线程状态由WAITING转变为BLOCKED(对应上图中的等待Blocked转变为锁定Blocked)。如下面第三段代码,线程t1获取test对象的对象锁后进入临界区,当执行锁对象的wait()方法后释放锁,并进入WAITING状态,接着线程t2获取该对象锁并调用notify方法唤醒线程t1,唤醒后的线程t1由于没有其它线程与它竞争test对象的锁资源,所以跳过BLOCKED状态,直接获取对象锁执行之后代码,此时t1状态为Runnable。                      

public class Test {public static void main(String[] args) {Test test = new Test();Thread t1 = new Thread(new Task1(test));t1.start();try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("t1等待:" + t1.getState());}public void waitTest() {synchronized (this) {System.out.println("t1运行:" + Thread.currentThread().getState());try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}}
}class Task1 implements Runnable {private Test test;public Task1(Test test) {this.test = test;}@Overridepublic void run() {test.waitTest();}
}

                   程序执行结果:

                                   

public class Test {public static void main(String[] args) {Thread t1 = new Thread(new Task1());Thread t2 = new Thread(new Task2(t1));t1.start();t2.start();try {System.out.println("t2运行:" + t2.getState());Thread.sleep(1000);System.out.println("t2等待:" + t2.getState());} catch (InterruptedException e) {e.printStackTrace();}}}class Task1 implements Runnable {@Overridepublic void run() {try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}}
}class Task2 implements Runnable {private Thread thread;public Task2(Thread thread) {this.thread = thread;}@Overridepublic void run() {try {for (int i = 0; i < 10000; i++) {}thread.join();} catch (InterruptedException e) {e.printStackTrace();}}
}

                    程序执行结果:

                             

public class Test {public static void main(String[] args) {Test test = new Test();Thread t1 = new Thread(new Task1(test));Thread t2 = new Thread(new Task2(test));t1.start();t2.start();try {Thread.sleep(1000);System.out.println("t1等待:" + t1.getState());} catch (InterruptedException e) {e.printStackTrace();}}public void waitTest() {System.out.println("t1运行:" + Thread.currentThread().getState());synchronized (this) {try {this.wait();System.out.println("t1唤醒后运行:"+ Thread.currentThread().getState());} catch (InterruptedException e) {e.printStackTrace();}}}public void notifyTest() {try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}synchronized (this) {this.notify();}}
}class Task1 implements Runnable {private Test test;public Task1(Test test) {this.test = test;}@Overridepublic void run() {test.waitTest();}}class Task2 implements Runnable {private Test test;public Task2(Test test) {this.test = test;}@Overridepublic void run() {test.notifyTest();}
}

              程序执行结果:

             


             5.TIMED_WAITING状态

          当线程分配到CPU时间片并在执行程序时,此时执行到的语句为线程的sleep()方法或对象的wait()方法(有timeout参数)或线程的join()方法(有timeout参数)时,线程由RUNNABLE状态转变为TIMED_WAITING状态(对应上图中的Running状态转变为Blocked状态)。下面第一段代码说明线程t1调用sleep()方法后进入TIMED_WAITING状态,休眠时间过去后重新转为RUNNABLE状态,另外sleep()方法是不释放锁的。第二段代码说明线程t1调用test对象的wait方法后进入TIMED_WAITING状态,等待时间过去后重新转为RUNNABLE状态,因为该wait()方法设置了等待时间,所以不需要通过其它线程来唤醒,等待时间过去后由系统自动唤醒该线程,另外wait()方法是释放锁的。第三段代码说明线程t2调用了线程t1的join方法后进入TIMED_WAITING状态,等待时间过去后重新转为RUNNABLE状态,join()方法底层也是通过wait()方法实现的         

public class Test {public static void main(String[] args) {Thread t1 = new Thread(new Task1());t1.start();try {System.out.println("t1运行:" + t1.getState());Thread.sleep(1000);System.out.println("t1等待:" + t1.getState());} catch (InterruptedException e) {e.printStackTrace();}}
}class Task1 implements Runnable {@Overridepublic void run() {try {for (int i = 0; i < 10000; i++) {}Thread.sleep(3000);System.out.println("t1重新运行" + Thread.currentThread().getState());} catch (InterruptedException e) {e.printStackTrace();}}
}

             程序执行结果:

                 

public class Test {public static void main(String[] args) {Test test = new Test();Thread t1 = new Thread(new Task1(test));t1.start();try {System.out.println("t1运行:" + t1.getState());Thread.sleep(1000);System.out.println("t1等待:" + t1.getState());} catch (InterruptedException e) {e.printStackTrace();}}public void waitTest() {synchronized (this) {try {this.wait(3000);} catch (InterruptedException e) {e.printStackTrace();}}}
}class Task1 implements Runnable {private Test test;public Task1(Test test) {this.test = test;}@Overridepublic void run() {for (int i = 0; i < 10000; i++) {}test.waitTest();System.out.println("t1重新运行:" + Thread.currentThread().getState());}
}

             程序执行结果:

                     

public class Test {public static void main(String[] args) {Thread t1 = new Thread(new Task1());Thread t2 = new Thread(new Task2(t1));t1.start();t2.start();try {System.out.println("t2运行:" + t2.getState());Thread.sleep(1000);System.out.println("t2等待:" + t2.getState());} catch (InterruptedException e) {e.printStackTrace();}}}class Task1 implements Runnable {@Overridepublic void run() {try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}}
}class Task2 implements Runnable {private Thread thread;public Task2(Thread thread) {this.thread = thread;}@Overridepublic void run() {try {for (int i = 0; i < 10000; i++) {}thread.join(3000);System.out.println("t2重新运行:" + Thread.currentThread().getState());} catch (InterruptedException e) {e.printStackTrace();}}
}

              程序执行结果:

              


              5.TERMINATED状态     

            当线程运行完run()方法后,就转变为此状态。如下代码说明了线程由RUNNABLE状态转变为TERMINATED状态(对应上图Running状态向Dead状态的转变)

public class Test {public static void main(String[] args) {Thread t1 = new Thread(new Task1());t1.start();try {System.out.println("t1运行:" + t1.getState());Thread.sleep(3000);System.out.println("t1死亡:" + t1.getState());} catch (InterruptedException e) {e.printStackTrace();}}
}class Task1 implements Runnable {@Overridepublic void run() {for (int i = 0; i < 10000; i++) {}}
}

          程序执行结果:    

            

        

        总结: 线程的这六种状态其实就是一个线程完整的生命周期,当我们了解了不同阶段的线程的各种状态之后,对于我们分析线程间的死锁,线程的IO资源等待等等都有很大的帮助,反映在系统层面上,当我们程序的CPU使用率突然变高或者程序响应时间突然变慢等问题都可以通过那一时刻的线程分析进行问题的定位。

        以上均为作者本人的自我总结,如有不到之处请指正~



http://chatgpt.dhexx.cn/article/ITPcWlsX.shtml

相关文章

python封装线程类(启动、终止、查看线程状态)

文章目录 一、简单说明二、实现步骤三、测试 一、简单说明 将启动、终止和查看线程状态的方法封装成类声明时传入要启动的方法通过 start、stop 和 state 执行启动、终止 和 查看状态 二、实现步骤 # encoding: utf-8import time import threading import inspect import ct…

一文搞懂线程世界级难题——线程状态到底是6种还是5种!!!

背景 先来解答一个世界级难题&#xff1a; java线程有多少种状态&#xff1f; 答案是6种&#xff01;&#xff01;&#xff01; 那为什么有的地方说是5种呢&#xff0c;那这一定是将操作系统层面的线程状态搞混了。 下面我们就分别介绍一下java线程的6种状态以及操作系统层…

Java线程状态

线程跟人类一样拥有自己的生命周期&#xff0c;一条线程从创建到执行完毕的过程即是线程的生命周期&#xff0c;此过程可能在不同时刻处于不同的状态&#xff0c;线程状态正是这小节的主题&#xff0c;线程到底有多少种状态&#xff1f;不同状态之间是如何转化的&#xff1f; …

java线程状态与操作系统线程状态的关系

清楚的理解和认知线程状态是java多线程的基础&#xff0c;多线程本质上其实就是管理多个线程的状态&#xff0c;以期在保证线程安全的情况下获得最佳的运行效率&#xff08;发挥cpu的最佳效能&#xff09; 首先列举几个容易混淆的线程状态问题文末进行解答&#xff1a; 1Java线…

Java 如何获取线程状态呢?

下文笔者讲述Java中获取线程状态的方法分享,如下所示: java线程状态的简介 Java中的线程整个生命周期中分为5种状态:1.新建状态(New):新建的线程都为此状态2.就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法该状态的线程在"可运行线程池"中,…

【线程】详解线程状态(到底是五种还是六种)

首先我们要知道&#xff0c;在传统&#xff08;操作系统&#xff09;的线程模型中线程被分为五种状态 在java线程中&#xff0c;线程被分为六种状态 传统线程模型&#xff08;操作系统&#xff09;中线程状态 线程的五种状态&#xff1a; 1.新建&#xff08;new&#xff09; 创…

Java线程状态RUNNABLE详解

Java虚拟机层面所暴露给我们的状态&#xff0c;与操作系统底层的线程状态是两个不同层面的事。具体而言&#xff0c;这里说的 Java 线程状态均来自于 Thread 类下的 State 这一内部枚举类中所定义的状态&#xff1a; 什么是 RUNNABLE&#xff1f; 直接看它的 Javadoc 中的说明…

Java多线程 - 线程状态

线程状态 五个状态&#xff1a;新生、就绪、运行、死亡、阻塞 停止线程 不推荐使用JDK提供的stop()、destroy()方法【已弃用】推荐线程自己停止建议用一个标志位进行终止变量&#xff0c;到flagfalse&#xff0c;则终止线程运行 public class StopDemo implements Runnab…

jstack线程状态分析

使用jstack pid命令可以查看JVM的线程状态,其中值得关注的线程状态有&#xff1a; 死锁&#xff0c;Deadlock&#xff08;重点关注&#xff09;执行中&#xff0c;Runnable等待资源&#xff0c;Waiting on condition&#xff08;重点关注&#xff09;等待获取监视器&#xff0…

多线程之线程状态

## 线程状态 五大状态 1.创建状态&#xff1a;Thread thread new Thread(); 线程对象一旦创建就进入了新生状态。 2.就绪状态&#xff1a;当调用start()方法时&#xff0c;进入就绪状态&#xff0c;但不代表立即调度执行&#xff08;等待cpu调度&#xff09;。 3.运行状态或同…

Java线程的6种状态及切换(透彻讲解)

Java中线程的状态分为6种。 1. 初始(NEW)&#xff1a;新创建了一个线程对象&#xff0c;但还没有调用start()方法。 2. 运行(RUNNABLE)&#xff1a;Java线程中将就绪&#xff08;ready&#xff09;和运行中&#xff08;running&#xff09;两种状态笼统的称为“运行”。 线程对…

线程的5种状态详解

概念 1.初始状态(NEW)&#xff1a;新创建了一个线程对象。 2.可运行状态(RUNNABLE)&#xff1a;线程对象创建后&#xff0c;其他线程(比如main线程&#xff09;调用了该对象的start()方法。该状态的线程位于可运行线程池中&#xff0c;等待被线程调度选中&#xff0c;获取cpu…

线程的五种状态

1.新建状态&#xff08;New&#xff09;&#xff1a; 创建一个新的线程对象。 2.就绪状态&#xff08;Runnable&#xff09;: 线程创建对象后&#xff0c;其他线程调用start()方法&#xff0c;该线程处于就绪状态&#xff0c;资源已经准备就绪&#xff0c;等待CPU资源。 3.…

线程的几种状态

目录 前言 一、线程是什么&#xff1f; 二、线程状态 1.新建状态&#xff08;New&#xff09; 2.就绪状态&#xff08;Runnable&#xff09; 3.运行状态&#xff08;Running&#xff09; 4.阻塞状态&#xff08;Blocked&#xff09; 5.等待状态/超时等待&#xff08;Wa…

Java的6种线程状态以及线程状态的转换

详细介绍了Java线程的6中状态&#xff0c;以及状态之间的转换。 文章目录 1 线程状态(生命周期)1.1 源码中的状态1.2 状态解释 2 线程状态转换2.1 进入等待/超时等待2.1.1 进入等待状态2.1.1.1 wait方法的介绍2.1.1.2 join方法的介绍 2.1.2 进入超时等待2.1.2.1 sleep方法的介绍…

Lombok 的 @Builder 的使用,默认值的设置,修改属性值

1&#xff0c;简单使用 2&#xff0c;属性默认值的设置问题 3&#xff0c;修改属性值 1&#xff0c;简单使用 他这个Builder注解&#xff0c;相比之前的编辑器自动生成的getter setter的优点在哪呢&#xff1f; 看下面的使用例子 package com.lxk.lombok;import com.lxk.m…

POJO属性定义包装类型还是基本类型

举个例子, private Boolean aaa;private boolean bbb;Boolean类型的变量会设置默认值为null&#xff0c;而boolean类型的变量会设置默认值为false。 也就是说&#xff0c;包装类型的默认值都是null&#xff0c;而基本数据类型的默认值是一个固定值&#xff0c;&#xff08;boo…

MybatisPlus自动填充公共字段及特定类型属性设置默认值

前言 MybatisPlus是一个 MyBatis的增强工具&#xff0c;集成了mybatis和hibernate各自的优点&#xff0c;所以很受一些企业的喜爱。目前我们公司就在使用&#xff0c;确实特别好用。本文重点介绍自动填充公共字段及特定字段类型设置默认值的方法。 之前写过一篇关于JPA和mybat…

map的value默认值问题

关于map的value的默认值问题 结论&#xff1a; bool ----默认值为-------> false; int/double... ----默认值为-------> 0; string ----默认值为-------> "";#include<bits/stdc.h> #include<unordered_map>…

JPA生成表 给列加默认值 以及columnDefinition 失效的问题

做项目的时候 持久层使用jpa jpa的一些设置可以在application.yml 中实现 比如每次启动项目的时候 根据类自动创建表 控制台显示sql语句 创建一些表的时候 我们希望设置默认的值 比如创建一张student表 Data Entity EntityListeners(AuditingEntityListener.class) publi…