Java 线程状态有哪些?

news2025/1/17 4:49:39

文章目录

  • Java 线程状态有哪些?
    • 初始状态(NEW)
    • 可运行状态(RUNNABLE)
      • 就绪状态
      • 运行状态
    • 阻塞状态(BLOCKED)
    • 等待状态(WAITING)
    • 超时等待(TIMED_WAITING)
    • 终止状态(TERMINATED)

Java 线程状态有哪些?

在线程的生命周期中,它需要经历初始状态、可运行状态、阻塞状态、等待状态、超时等待状态和终止状态。线程的状态流转如下图所示。

在这里插入图片描述

下面的示例代码都继承自类,用来按步骤(模拟时间序列)输出线程的状态。

package org.gettingreal.juc.learning.thread;

/**
 * 线程状态打印类
 */
public class ThreadStatePrinter {

    // 记录步骤
    private static volatile int STEP = 0;

    // 打印状态
    public static void printState(Thread thread) {
        System.out.println("STEP: " + (++STEP) + ", " + thread.getName() + "'s state: " + thread.getState());
    }

}

初始状态(NEW)

继承 Thread 类,或者类实现 Runnable 接口并将其传递给 Thread 类,使用 new 操作符来创建一个线程,线程此时的状态是初始状态。

package org.gettingreal.juc.learning.thread;

/**
 * 线程初始化状态测试
 */
public class ThreadNewStateTest extends ThreadStatePrinter {

    public static void main(String[] args) {
        Thread t = new Thread();
        printState(t);

        // 输出
        // STEP: 1, Thread-0's state: NEW
    }

}

可运行状态(RUNNABLE)

线程的可运行状态较为复杂,因为隐喻了就绪状态和运行状态。

就绪状态

就绪状态,是指线程有被运行的可能,CPU 分配给该线程时间片,该线程就会进入运行状态。

下面是线程进入就绪状态的场景:

  • 调用线程的 start() 方法
  • 线程 sleep() 方法结束
  • 其他线程 join() 结束
  • 时间片用完或调用线程的 yield() 方法
  • 锁池里面的线程拿到锁后

通过 start() 方法使得线程进入 RUNNABLE 状态。

package org.gettingreal.juc.learning.thread;

/**
 * 线程 RUNNABLE 状态测试
 */
public class ThreadRunnableStateWithStartTest extends ThreadStatePrinter {

    public static void main(String[] args) {
        Thread t = new Thread();
        printState(t);

        t.start();
        printState(t);

        // 输出
        // STEP: 1, Thread-0's state: NEW
        // STEP: 2, Thread-0's state: RUNNABLE
    }

}

线程 sleep() 方法结束,进入 RUNNABLE 状态。

package org.gettingreal.juc.learning.thread;

/**
 * 线程 RUNNABLE 状态测试
 */
public class ThreadRunnableStateWithSleepTest extends ThreadStatePrinter {


    public static void main(String[] args) throws Exception {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    // 触发睡眠
                    Thread.sleep(3000);

                    // 睡眠之后打印该线程的状态
                    printState(Thread.currentThread());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        printState(t);

        t.start();
        printState(t);

        // 主线程睡眠 1 秒中,为了输出睡眠中线程的状态
        Thread.sleep(1000);
        printState(t);

        // 输出
        // STEP: 1, Thread-0's state: NEW
        // STEP: 2, Thread-0's state: RUNNABLE
        // STEP: 3, Thread-0's state: TIMED_WAITING
        // STEP: 4, Thread-0's state: RUNNABLE
    }

}

可以看出,当线程调用 sleep() 方法后,线程进入 TIMED_WAITING 状态,等到 sleep 结束,线程又进入到 RUNNABLE 状态。

其他线程 join 结束,线程进入 RUNNABLE 状态。

package org.gettingreal.juc.learning.thread;

/**
 * 线程 RUNNABLE 状态测试
 */
public class ThreadRunnableStateWithSleepTest extends ThreadStatePrinter {

    private static Thread parentThread;
    private static Thread childThread;

    public static void main(String[] args) throws Exception {
        childThread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    // 触发睡眠
                    Thread.sleep(3000);

                    // 睡眠之后打印父线程的状态
                    printState(parentThread);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        childThread.setName("childThread");

        parentThread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {

                    childThread.start();
                    childThread.join();

                    // join 结束后打印父线程状态
                    printState(parentThread);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        parentThread.setName("parentThread");

        printState(parentThread);

        parentThread.start();
        printState(parentThread);


        // 输出
        // STEP: 1, parentThread's state: NEW
        // STEP: 2, parentThread's state: RUNNABLE
        // STEP: 3, parentThread's state: WAITING
        // STEP: 4, parentThread's state: RUNNABLE
    }

}

可以看出,parentThread 线程在 WAITING 状态之后又恢复到 RUNNABLE 状态。

时间片用完或者调用 yield() 方法。

package org.gettingreal.juc.learning.thread;

/**
 * 线程 RUNNABLE 状态测试
 */
public class ThreadRunnableStateWithYieldTest extends ThreadStatePrinter {

    public static void main(String[] args) {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                printState(Thread.currentThread());

                // 正在运行中的线程,时间片用完或者调用 yield 方法,都会让线程进入 RUNNABLE 抓给你台
                Thread.yield();

                printState(Thread.currentThread());
            }
        });
        printState(t);

        t.start();
        printState(t);

        // 输出
        // STEP: 1, Thread-0's state: NEW
        // STEP: 2, Thread-0's state: RUNNABLE
        // STEP: 3, Thread-0's state: RUNNABLE
        // STEP: 4, Thread-0's state: RUNNABLE
    }

}

运行状态

从就绪状态的线程中选择一个线程,分配给其 CPU 时间片来运行,该线程就进入运行状态。

阻塞状态(BLOCKED)

当线程无法获取锁时,就会进入到阻塞状态。

package org.gettingreal.juc.learning.thread;

/**
 * 线程阻塞状态测试
 */
public class ThreadBlockedStateTest extends ThreadStatePrinter {

    // 使用对象来模拟一把锁
    private static Object lock = new Object();
    private static Thread oneThread;
    private static Thread anotherThread;

    public static void main(String[] args) throws Exception {
        oneThread = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lock) {
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        oneThread.setName("oneThread");

        anotherThread = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lock) {
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        anotherThread.setName("anotherThread");
        printState(oneThread);
        printState(anotherThread);

        oneThread.start();
        anotherThread.start();

        printState(oneThread);
        printState(anotherThread);

        Thread.sleep(1500);

        printState(oneThread);
        printState(anotherThread);

        Thread.sleep(1500);
        printState(oneThread);
        printState(anotherThread);

        // 输出
        // STEP: 1, oneThread's state: NEW
        // STEP: 2, anotherThread's state: NEW
        // STEP: 3, oneThread's state: TIMED_WAITING
        // STEP: 4, anotherThread's state: RUNNABLE
        // STEP: 5, oneThread's state: TIMED_WAITING
        // STEP: 6, anotherThread's state: BLOCKED
        // STEP: 7, oneThread's state: TERMINATED
        // STEP: 8, anotherThread's state: TIMED_WAITING
    }

}

可以看到在第六步时,anotherThread 的状态是 BLOCKED,因为该线程也需要获得 lock 锁才能执行 synchronized 块里面的逻辑。

等待状态(WAITING)

处于等待状态的线程不会被分配 CPU 执行时间,要被显式地唤醒(调用 notify() 方法),否则会处于一直等待的状态。调用 wait() 方法会释放锁,线程会进入等待锁池中。

package org.gettingreal.juc.learning.thread;

/**
 * 线程等待状态测试
 */
public class ThreadWaitingStateTest extends ThreadStatePrinter {

    private static final Object lock = new Object();

    public static void main(String[] args) throws Exception {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lock) {
                    try {
                        // 调用 wait 方法进入等待状态
                        lock.wait();

                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });

        printState(t);

        t.start();
        printState(t);

        // 睡眠 1 秒钟,让 t 线程的 wait() 方法得到执行
        Thread.sleep(1000);
        printState(t);

        // 通知线程 t
        synchronized (lock) {
            lock.notify();
            printState(t);
        }

        // 输出
        // STEP: 1, Thread-0's state: NEW
        // STEP: 2, Thread-0's state: RUNNABLE
        // STEP: 3, Thread-0's state: WAITING
        // STEP: 4, Thread-0's state: BLOCKED
    }

}

在线程上调用 wait() 方法,该线程会进入 WAITING 状态,释放 lock 锁。后面的 BLOCKED 状态是因为执行完 notify() 方法之后,线程需要再次获取 lock 锁。

超时等待(TIMED_WAITING)

线程处于超时等待状态的不会被分配 CPU 执行时间,也无需被唤醒,当然也不会释放对应的锁。

package org.gettingreal.juc.learning.thread;

/**
 * 线程超时等待状态测试
 */
public class ThreadTimedWaitingStateTest extends ThreadStatePrinter {

    private static final Object lock = new Object();

    public static void main(String[] args) throws Exception {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        printState(t);

        t.start();
        printState(t);

        // 睡眠 1 秒钟,让 t 线程的 wait() 方法得到执行
        Thread.sleep(1000);
        printState(t);

        // 输出
        // STEP: 1, Thread-0's state: NEW
        // STEP: 2, Thread-0's state: RUNNABLE
        // STEP: 3, Thread-0's state: TIMED_WAITING
    }

}

终止状态(TERMINATED)

线程的 run() 方法执行完成后,该线程的状态就是终止状态了。

package org.gettingreal.juc.learning.thread;

/**
 * 线程终止状态测试
 */
public class ThreadTerminatedStateTest extends ThreadStatePrinter {

    private static final Object lock = new Object();

    public static void main(String[] args) throws Exception {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {

            }
        });

        printState(t);

        t.start();
        printState(t);

        // 睡眠 1 秒钟,让 t 线程的 wait() 方法得到执行
        Thread.sleep(1000);
        printState(t);

        // 输出
        // STEP: 1, Thread-0's state: NEW
        // STEP: 2, Thread-0's state: RUNNABLE
        // STEP: 3, Thread-0's state: TERMINATED
    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/435330.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一次打靶场记录

题目提示 1、目录爆破 在对靶场进行信息收集、目录扫描之后发现结果存在www.zip,data.zp 两个备份文件 下载回来解压之后发现www.zip是网站备份文件,data.zip是数据库文件,存在一个maccms的数据库 苹果cms的数据库,导入本地数据库。 admin…

【并发编程Python】为什么Python这么慢

Python速度慢的所有原因 Python作为一门非常优秀的计算机语言,其速度慢给Python减了很多分,也是其一直被诟病的主要原因之一,通常情况下,Python比Java/C慢约5-10倍,在一些特殊的情况下Python甚至比C慢100~200倍&#x…

数据结构——B树和B+树

数据结构——B树和B树 一、B树1.B树的特征2.B树的插入操作3.B树的删除操作4.B树的缺点 二、B树B树的特征 平衡二叉树或红黑树的查找效率最高,时间复杂度是O(nlogn)。但不适合用来做数据库的索引树。 因为磁盘和内存读写速度有明显的差距,磁盘中存储的数…

玩转肺癌目标检测数据集Lung-PET-CT-Dx ——③整理、验证数据,建立Dataset对象

文章目录 数据整理整理出所有的dcm文件整理出所有的xml标注文件整理数据①——舍弃错误的标注文件整理数据②——两个标注文件指向同一个目标图片的情况封装函数,传入xml文件,显示标注效果 整理数据③——将PETCT的三通道图像转成平扫CT的单通道图像格式…

企业费控,驶向「一体化」

在数字化于企业内部各个环节实现平权、成为标配的当下,财务,这个被称为“控制企业生命力”的核心环节,是否应该拥有新的价值? 作者| 皮爷 出品|产业家 2022年年中,施伟和分贝通的团队接到一项“特殊需求”。 这个…

在职读研专业——劳动经济学

研究方向:劳动经济学主要研究劳动力市场现象及其所引起的劳动力资源配置等相关问题,包括劳动力供给、劳动力需求、就业、工资、人力资本投资、收入分配等。例如:劳动力市场失衡背后各种因素的变化,如何通过资源的配置使劳动资源配…

MySQL innobackupex 备份工具使用总结

前言 在MySQL备份以及搭建从库的过程中,我们针对比较小的库大多采用的是mysqldump,简单,方便。但是在大库进行搭建从库的时候,且数据库主机没有一个很好的存储来满足备份,这个时候就需要使用innobackupex来协助你来做一…

Pocsuite3框架POC/EXP编写练习:Flask(Jinja2) 服务端模板注入漏洞

Pocsuite3 是由知道创宇 404 实验室打造的一款基于 GPLv2 许可证开源的远程漏洞测试框架。可以用来编写POC/EXP,今天借助Flask框架下的SSTI漏洞练习记录一下Pocsuite3框架的配置和编写过程。 官方文档:Pocsuite3 是什么? | Pocsuite3 安装 …

小黑继续跟着沛奇老师学携程:携程基础3

3.异步编程 3.1事件循环 理解成一个死循环,去检测并执行某些代码 # 伪代码任务列表 [任务1,任务2,任务3,...] while True:可执行的任务列表,已完成的任务列表 去任务列表中检查所有任务,将可执行和已完…

安装、启动和登陆doccano

一、安装 1、使用的Pycharm安装的doccano 2、初始化数据库 doccano init 3、创建用户名和密码 # admin是用户名,pass是密码,都可以自定义 doccano createuser --username admin --password pass 二、启动 1、在一个Terminal终端启动webserver服务 …

自适应控制专栏目录及介绍

目录 自适应控制专栏目录及介绍第一篇:[具有不确定参数系统的自适应跟踪控制设计_ADi_hhh的博客-CSDN博客](https://blog.csdn.net/qq_45830323/article/details/129713051)第二篇:[(SISO)单输入单输出系统的模型参考自适应控制_A…

cdh Hue集成sentry的权限管理详细步骤

hue登录hue的第一个用户要用hue用户创建,默认hue为超级用户,hue用户页面的权限可以管理很多用户操作,比如查看hdfs目录,使用其他组件,授权功能等等 一.hive的配置 1.关闭模拟,开启sentry 2.添加配置(注意配置的位置) <property> <name>sentry.hive.tes…

【C++11】lambda表达式

目录 lambda表达式 1.1 lambda表达式出现的原因 1.2 lambda表达式语法 1.3 函数对象与lambda表达式 lambda表达式 1.1 lambda表达式出现的原因 在C98中&#xff0c;如果想要对一个数据集合中的元素进行排序&#xff0c;可以使用 std::sort 方法 测试代码 #include <…

苹果撤离中国市场?中国市场太重要,印度制造是备胎

苹果在中国之行后&#xff0c;却计划进一步扩大印度制造iPhone的比例&#xff0c;甚至将iPhone15全数交给印度制造&#xff0c;业界因此认为苹果正在离开中国市场&#xff0c;然而这完全是臆想&#xff0c;中国市场对苹果来说仍然非常重要&#xff0c;它不会轻易舍弃这个市场。…

【Unity VR开发】结合VRTK4.0:添加碰撞忽略器

语录&#xff1a; 最远的旅行&#xff0c;是从自己的身体到自己的心&#xff0c;是从一个人的心到另一个人的心。坚强不是面对悲伤不流一滴泪&#xff0c;而是擦干眼泪后微笑面对以后的生活。 前言&#xff1a; 模块化提供了一种允许两个或者多个对象忽略彼此碰撞的方法&#x…

Logstash:多管道配置

我们大多数人已经熟悉 Elastic 产品。 在此博客中&#xff0c;我们将逐步介绍配置 Logstash 以使用多个管道摄取和处理数据的步骤。 Logstash 是一种开源数据处理管道&#xff0c;可让你摄取、转换和输出数据。 它是从各种来源收集和处理大量数据的强大工具&#xff0c;可用于管…

IP协议头

IP 4位版本号&#xff08;version&#xff09;4位头部长度&#xff08;header length&#xff09;8位服务类型&#xff08;Type Of Service&#xff09;16位总长度&#xff08;total length&#xff09;16位标识&#xff08;id&#xff09;3位标志字段13位分片偏移&#xff08;…

Spring的循环依赖

什么是循环依赖&#xff1f; 循环依赖其实就是循环引用&#xff0c;也就是两个或者两个以上的 bean 互相持有对方&#xff0c;最终形成闭环。比如 A 依赖于 B&#xff0c;B 依赖于 C&#xff0c;C 又依赖于 A。如下图&#xff1a; 注意&#xff0c;这里不是函数的循环调用&…

金陵科技学院五年一贯制专转本计算机应用基础考试大纲

金陵科技学院五年一贯制专转本计算机应用基础考试大纲 一、参考书目&#xff1a; 《大学计算机信息技术教程》&#xff0c;张福炎&#xff0c;孙志挥&#xff0c;南京大学出版社&#xff0c;《全国计算机等级考试一级教程计算机基础及MS Office应用》&#xff0c;教育部考试中…

书写我的人生回忆录-这应该是给子女和父母最好的礼物

作为一个业余的软件开发爱好者&#xff0c;我又捣鼓了一个有意思的小东西 &#xff0c;使用完全免费哈 您可以是以子女的身份帮助父母来完成这份回忆录&#xff1a; 《书写我的人生回忆录》是一款软件&#xff0c;其中包含70个问题&#xff0c;涵盖了父母的个人喜好、家庭、工…