Java之线程状态

news2024/10/2 8:33:32


一、简介

线程的六种状态:

  • New - 新建状态;
  • Runnable - 运行状态;
  • Blocked - 被阻塞状态;
  • Waiting - 等待状态;
  • TimeWaiting - 超时等待状态;
  • Terminated - 终止状态;

线程状态之间的转换图:请添加图片描述


二、线程状态

1、新建状态(New)

  • New:线程被创建,但尚未启动的状态。

当我们用 new Thread(); 新建一个线程时,如果线程没有开始执行 start() 方法,所以没有开始执行 run() 方法里面的代码,那么线程此时的状态就是 New。而一旦线程调用了 start() 方法,它的状态就会从 New 变成 Runnable


2、运行状态(Runnable)

Java 中的 Runnable 状态对应操作系统线程状态中的两种状态:

  • Runnable - 运行状态;
  • Ready - 就绪状态,正在等待被分配 CPU 资源;

如果一个正在运行的线程是 Runnable 状态,当它运行到任务的一半时,执行该线程的 CPU 被调度去做其他事情,导致该线程暂时不运行,它的状态依然是 Runnable,因为它有可能随时被调度回来继续执行任务。


3、阻塞状态(Blocked/Waiting/TimeWaiting)

Java 中阻塞状态包括三种状态:

  • Blocked - 被阻塞状态;

  • Waiting - 等待状态;

  • TimeWaiting - 超时等待状态;


(1)被阻塞状态(Blocked)

线程 Blocked 状态的转换:

  • Runnable 状态进入 Blocked 状态:进入 synchronized 保护的代码(包括:synchronized代码块synchronized方法)时没有抢到 monitor 锁。

  • Blocked 状态回到 Runnable 状态:处于 Blocked 的线程抢到 monitor 锁。


(2)等待状态(Waiting)

线程进入 Waiting 状态有以下三种可能:

  • run() 方法中调用 Object.wait()

  • run() 方法中调用 Thread.join()

  • run() 方法中调用 LockSupport.park()

前面强调了 Blocked 是针对 synchronized monitor 锁,可是在 Java 中还有很多其他锁,比如 ReentrantLock,如果线程在获取这种锁时,没有抢到该锁,就会进入 Waiting 状态,因为本质上它执行了 LockSupport.park() 方法,所以会进入 Waiting 状态,同样,Object.wait()Thread.join() 也会让线程进入 Waiting 状态。


BlockedWaiting 的区别:

  • Blocked 在等待其他线程释放 monitor 锁;

  • Waiting 在等待某个条件,比如 join 的线程执行完毕或者是 notify() / notifyAll()

Waiting 状态流转到其他状态比较特殊,因为 Waiting 是不限时的,也就是说无论过了多长时间它都不会主动恢复。


线程 Waiting 状态的转换:

  • 当执行了 LockSupport.unpark(),或者 join() 的线程运行结束,或者被中断时,线程才会从 Waiting 状态进入 Runnable 状态;

  • 其他线程如果调用了 notify()notifyAll() 来唤醒它,线程会直接进入 Blocked 状态(因为唤醒 Waiting 线程的线程如果调用了 notify()notifyAll(),要求首先要持有该 monitor 锁,所以处于 Waiting 状态的线程被唤醒时拿不到该锁,就会进入 Blocked 状态,直到执行了 notify() / notifyAll() 的唤醒它的线程执行完毕并释放了 monitor 锁,才可能轮到它去抢夺这把锁,如果它能抢到,就会从 Blocked 状态回到 Runnable 状态);


(3)超时等待状态(TimeWaiting)

TimeWaitingWaiting 状态非常相似,区别仅仅在于有没有超时限制,TimeWaiting 会等待超时,由系统自动唤醒,或者在超时前被唤醒信号唤醒。


线程进入 TimeWaiting 状态有以下几种可能:

  • run() 方法中调用 Thread.sleep(sleeptime)

  • run() 方法中调用 Object.wait(timeout)

  • run() 方法中调用 Thread.join(timeout)

  • run() 方法中调用 LockSupport.parkNanos(timeout)

  • run() 方法中调用 LockSupport.parkUntil(timeout)


线程 TimeWaiting 状态的转换:

  • 如果 TimeWaiting 超时时间未超时,当其他线程调用了 notify()notifyAll()TimeWaiting 状态的线程会先进入 Blocked 状态,然后抢夺 monitor 锁成功后,再会进入到 Runnable 状态,此种情况下 TimeWaitingWaiting 状态一样的;

  • 如果 TimeWaiting 超时时间超时,且能直接获取到锁 / join的线程运行结束 / 被中断 / 调用了LockSupport.unpark(),会直接恢复到 Runnable 状态;


4、终止状态(Terminated)

进入终止状态的两种可能:

  • 线程正常退出run() 方法执行完毕;

  • 线程意外终止:出现一个没有捕获的异常,终止了 run() 方法;


三、总结

线程状态总结:

  • new Thread(),但没有调用 start() 方法,线程处于 New 状态;

  • new Thread(),且调用了 start() 方法,线程处于 Runnable 状态;

  • new Thread(),且调用了 start() 方法,run() 方法中调用了 thread.join()object.wait() 方法,线程处于 Waiting 状态;

  • new Thread(),且调用了 start() 方法,run() 方法中调用了 Thread.sleep(sleeptime) 方法,线程处于 TimeWaiting 状态;

  • new Thread(),且调用了 start() 方法,run() 方法中获取 monitor 锁,且没有获取到,线程处于 Blocked 状态;

  • new Thread(),且调用了 start() 方法,run() 方法正常执行完毕或抛出未捕获的异常而结束,线程处于 Terminated 状态;


线程转换注意事项:

  • 线程状态是需要按照箭头方向流转:比如线程从 New 状态是不可以直接进入 Blocked 状态的,它需要先经历 Runnable 状态;

  • 线程生命周期不可逆:一旦进入 Runnable 状态就不能回到 New 状态,一旦终止就不可能再有任何状态变化,所以一个线程只能有一次 NewTerminated 状态,只有处于中间状态才可以相互转换;


四、示例

六种线程状态示例:

package com.cw.tsb.test;

/**
 * @author Davis
 * @Date 2022-12-29 11:27 上午
 */
public class ThreadStateTest {
    public static void main(String[] args) {
        threadState();
    }

    private static void threadState(){
        Thread t1 = new Thread("t1") {
            @Override
            public void run() {
                System.out.println("running...");
            }
        };

        Thread t2 = new Thread("t2") {
            @Override
            public void run() {
                while(true) { // runnable

                }
            }
        };
        t2.start();

        Thread t3 = new Thread("t3") {
            @Override
            public void run() {
                System.out.println("running...");
            }
        };
        t3.start();

        Thread t4 = new Thread("t4") {
            @Override
            public void run() {
                synchronized (ThreadStateTest.class) {
                    try {
                        Thread.sleep(1000000); // timed_waiting
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        t4.start();

        Thread t5 = new Thread("t5") {
            @Override
            public void run() {
                try {
                    t2.join(); // waiting
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        t5.start();

        Thread t6 = new Thread("t6") {
            @Override
            public void run() {
                synchronized (ThreadStateTest.class) { // blocked
                    try {
                        Thread.sleep(1000000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        t6.start();

        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("t1 state : " + t1.getState());
        System.out.println("t2 state : " + t2.getState());
        System.out.println("t3 state : " + t3.getState());
        System.out.println("t4 state : " + t4.getState());
        System.out.println("t5 state : " + t5.getState());
        System.out.println("t6 state : " + t6.getState());
    }
}

输出结果:

running...
t1 state : NEW
t2 state : RUNNABLE
t3 state : TERMINATED
t4 state : TIMED_WAITING
t5 state : WAITING
t6 state : BLOCKED



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

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

相关文章

新新新~Revit插件【建模助手】7大模块介绍

年底了,大家是不是都在喝茶、聊天、等跨年;而我,建模助手,则在——总结、规划、PPT。 不盘不知道,一盘可吓了我一大跳!没想到咱们在过去一年居然建设了这么多丰功伟绩: 说点标志性的&#xff…

到底什么是电子管(真空管)?

1883年,著名发明家托马斯爱迪生(Thomas Edison)在一次实验中,观察到一种奇怪现象。当时,他正在进行灯丝(碳丝)的寿命测试。在灯丝旁边,他放置了一根铜丝,但铜丝并没有接在…

WebRTC系列-视频VideoBroadcaster与视频流

文章目录 1. VideoBroadcaster 添加sink2. VideoBroadcaster 视频数据分发OnFrame方法在前面的文章视频的采集流程中,视频数据采集完成后到编码器之前,如果需要渲染处理那里需要两路视频,WebRTC是实现了一个视频分发器VideoBroadcaster;用来分发采集的视频帧; 这篇文章主要…

Nginx网页配置工具nginxWebUI

今天应该是我们公司 2022 年最后一天上班了,给自己做个简单的年度总结吧: 1月:做核酸 2月:做核酸 3月:做核酸,半个月左右居家办公 4月:做核酸,静态管理 5月:做核酸&…

贪吃蛇基础·框架版(简单)开头有原码

更新不易,麻烦多多点赞,欢迎你的提问,感谢你的转发, 最后的最后,关注我,关注我,关注我,你会看到更多有趣的博客哦!!! 喵喵喵,你对我…

XStream < 1.4.20 栈缓冲区溢出漏洞

漏洞描述 XStream 是一个轻量级的、简单易用的开源Java类库,它主要用于将对象序列化成XML(JSON)或反序列化为对象。 在1.4.20之前的版本中存在栈缓冲区溢出漏洞,从而导致通过操纵已处理的输入流来造成拒绝服务。 在使用集合和映…

一文掌握FastDeploy Serving服务化部署(打造线上证件照制作系统,含完整代码)

目录一、概述1.1 服务化部署1.2 FastDeploy简介二、搭建线上证件照制作系统2.1 准备环境2.1.1 安装Docker2.1.2 安装NVIDIA Container Toolkit2.1.3 获取FastDeploy Serving镜像2.2 部署模型2.2.1 准备模型仓库2.2.2 编写配置文件config.pbtxt2.2.3 服务启动2.3.4 测试访问2.3 …

盒子模型、CSS 中选择器优先级以及权重计算、px、em 和 rem 的区别

CSS 的盒模型? 盒子模型(Box Modle)可以用来对元素进行布局,包括内边距,边框,外边距,和实际 内容这几个部分 盒子模型分为两种 第一种是 W3C 标准的盒子模型(标准盒模型)…

微软 Outlook 如何修改邮件列表中的字体或字号

因为电脑的操作系统是默认英文的,默认的字体实在是太难看了。 解决方案 我们是可以对字体进行修改的。 例如修改成下面的方案。 选择视图 首先,先选定顶部的视图。 然后在当前的视图下,选择视图设置。 随后在弹出的窗口中,选择…

一劳永逸解决latex 80%bug

Latex编辑器也用过很多了,这种问题出现,一般就是}没对应啥的,但是这次检查了半天,就是找不到问题。 最后有一个快捷的解决方案,就是overleafhttps://www.overleaf.com/project/6347bab20a4c120392547ff3 写文章五六年…

美颜sdk是如何美化皮肤的?

当下,互联网娱乐飞速发展,一些社交拍摄的平台逐渐爆火,例如短视频和直播类平台,此类平台基本都需要真人出镜,因此大家或多或少都有些“颜值焦虑”,平台方也正是因为这个原因,开始为大家接入美颜…

Mathorcup数学建模竞赛第五届-【妈妈杯】D题:图像去噪中几类稀疏变换的矩阵表示(附特等奖获奖论文和matlab代码实现)

赛题描述 假设一幅二维灰度图像 X 受到加性噪声的干扰:Y=X+N , Y 为观察到的噪声图像, N 为噪声。通过对于图像 Y 进行稀疏表示可以达到去除噪声的目的。任务: 2. 利用 Cameraman 图像中的一个小图像块(见图 1 )进行验证。 3. 分析稀疏系数矩阵,比较四种方法…

写作历时一个月,长达8000字的年终总结——[2022年终总结]不要怕,请勇敢的向前走

个人博客:武师叔 ❤️ 做一个有趣而不甘平庸的人!!❤️ 哈喽哈喽,好久不见,我的老朋友最近还好吗 距离上次7.21凌晨1:06完稿的【年中总结】,下半年也匆匆过去啦~ 其实总的来说,下半年过得并不…

医药流通企业如何安全访问医药ERP?无需公网IP和改变现有IT架构

随着目前医药流通行业竞争的加剧,市场供应日趋饱和,传统的粗放式管理缺陷逐渐暴露,导致从事医药行业企业的利润不同程度的下滑,想要满足医药行业客户的个性化需求,为适应企业未来发展,医药流通行业越来越多…

2022 IoTDB Summit:Apache IoTDB PMC 张金瑞《为物联网场景优化的时序数据库共识协议》...

12 月 3 日、4日,2022 Apache IoTDB 物联网生态大会在线上圆满落幕。大会上发布 Apache IoTDB 的分布式 1.0 版本,并分享 Apache IoTDB 实现的数据管理技术与物联网场景实践案例,深入探讨了 Apache IoTDB 与物联网企业如何共建活跃生态&#…

再学C语言19:循环控制语句——关系运算符

关系表达式&#xff08;relational expression&#xff09;&#xff1a;进行比较的判断表达式 关系运算符&#xff08;relational operator&#xff09;&#xff1a;关系表达式中出现的运算符 一、关系运算符 关系运算符运算符含义<小于<小于或等于等于>大于或等于&…

第二十一讲:神州路由器RIP路由的配置

设备 端口 IP 子网掩码 网关 Router-A F0/0 192.168.1.1 255.255.255.0 无 F0/3 192.168.10.1 255.255.255.0 无 Router-B F0/0 192.168.1.2 255.255.255.0 无 F0/3 192.168.20.1 255.255.255.0 无 PC1 192.168.10.2 255.255.255.0 192.168.10.1 PC…

超店有数丨tiktok必备选品和带货技巧!小白秒变大神!

有一些刚刚入门的小白缺乏跨境电商选品灵感&#xff0c;苦于不知道从哪里挖掘爆款产品&#xff0c;不知如何发现热门商家。如果你也面临着这些困扰&#xff0c;可以试试超店有数&#xff0c;它是专业的第三方数据服务平台&#xff0c;能够帮助商家发现热门种草视频、进行小店数…

【C++、数据结构】二叉搜索树 模拟实现

文章目录&#x1f4d6; 前言1. 二叉搜索树2. 二叉搜索树的模拟实现2.1 结点的声明2.2 基本的几个成员函数非递归版本&#xff08;1&#xff09;查找&#xff1a;&#xff08;2&#xff09;插入&#xff1a;&#xff08;4&#xff09;删除&#xff1a;&#xff08;重点&#xff…

你阳了吗?可以接种最新加强针疫苗了!

今天不聊技术&#xff0c;唠唠嗑。刚才得知室友全部阳了&#xff0c;不知道我还能撑到多会&#x1f926;‍♂️当前时间&#xff0c;距离全国抗疫政策转向已有一个月时间&#xff0c;大家都不可避免的直面新冠病毒。奥密克戎的传播能力果然很强&#xff0c;短短半个月时间从周围…