【Java并发】聊聊线程的几种状态

news2024/9/30 3:20:20

线程状态

线程的状态 在Thread中有一个枚举类进行标识

    /**
     * 线程状态
     *
     * NEW 尚未启动的线程处于这种状态
     * RUNNABLE 在 JVM 上执行的线程处于这种状态
     * BLOCKED 被阻止等待监视器锁的线程处于这种状态
     * WAITING 即无限期地等待另一个线程来执行某一特定操作的线程处于这种状态
     * TIMED_WAITING 正在等待另一个线程来达到一个指定的等待时间执行动作的线程处于这种状态
     * TERMINATED 已退出的线程处于这种状态
     * 一个线程可以在给定时间点只能处于一种状态。这些状态是 JVM 的状态并没有反映任何操作系统线程状态
     *
     * @see #getState
     */
    public enum State {
        /**
         * 线程还没有启动
         */
        NEW,

        /**
         * 运行中的线程
         */
        RUNNABLE,

        /**
         * 阻塞的,可能是在等待进入同步块/方法时被阻塞的
         * WAITING 不同在于, BLOCKED 是还没有进入同步块/方法时被阻塞,WAITING 是已经进去到获取同步块的过程中了,但却获取不到锁
         */
        BLOCKED,

        /**
         * 等待,遇到 Object#wait()、Thread.join、LockSupport#park() 这些方法时,线程就会等待
         * 等待另外一个线程执行特定的操作
         * 一个线程 Object.wait() 后,需要等待另外一个线程执行同一个 Object 的 notify()
         * 或者线程执行 thread1.join(),等待 thread1 来打断
         */
        WAITING,

        /**
         * 等待一定的时间
         */
        TIMED_WAITING,

        /**
         * 终止线程
         */
        TERMINATED;
    }

总体上来说其实就是 新建、可运行、无限等待、有限等待、阻塞、结束。
重点掌握的其实就是无限等待、有限等待、阻塞这三种。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

演示

NEW

    public static class ThreadTask implements Runnable {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + " 执行前");
            System.out.println(Thread.currentThread().getName() + " 执行后");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(new ThreadTask());
        TimeUnit.SECONDS.sleep(1);
        System.out.println(t1.getName() + "  stateName :" + t1.getState());
    }
Thread-0  stateName :NEW

RUNNABLE

t1.start(); // 获取线程状态就是运行态
Thread-0  stateName :RUNNABLE

TERMINATED

线程执行完毕,之后就会终止

Thread-0  stateName :TERMINATED

BLOCKED

BLOCKED阻塞状态 其实就是在syn修饰的方法、代码块中 同一时刻没有获取到锁,进入BLOCKED阻塞状态。


    private Object o = new Object();

    public static class ThreadTask implements Runnable {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + " 执行前");
            try {
                doExec();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " 执行后");
        }

        synchronized void doExec() throws InterruptedException {
            TimeUnit.SECONDS.sleep(10);
            System.out.println(Thread.currentThread().getName() + " 执行中");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ThreadTask threadTask = new ThreadTask();
        Thread t1 = new Thread(threadTask);
        t1.start();
        TimeUnit.SECONDS.sleep(1);

        Thread t2 = new Thread(threadTask);
        t2.start();

        System.out.println(t1.getName() + "  stateName :" + t1.getState());
        System.out.println(t2.getName() + "  stateName :" + t2.getState());
    }
Thread-0  stateName :TIMED_WAITING
Thread-1  stateName :BLOCKED

WAITING

wait

获得syn隐士锁的时候,调用了无参的wait() 方法,线程进入wait() . 需要调用notify/ nofityAll()进行唤醒。


    private Object o = new Object();

    public static class ThreadTask implements Runnable {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + " 执行前");
            try {
                doExec();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " 执行后");
        }

        synchronized void doExec() throws InterruptedException {
            wait();
            System.out.println(Thread.currentThread().getName() + " 执行中");
        }

        synchronized void doNotify() throws InterruptedException {
            notify();
            System.out.println(Thread.currentThread().getName() + " 执行中");
        }

        synchronized void donotifyAll() throws InterruptedException {
            notifyAll();
            System.out.println(Thread.currentThread().getName() + " 执行中");
        }

    }

    public static void main(String[] args) throws InterruptedException {
        ThreadTask threadTask = new ThreadTask();
        Thread t1 = new Thread(threadTask);
        t1.start();
        TimeUnit.SECONDS.sleep(1);
        System.out.println(t1.getName() + "  stateName :" + t1.getState());
//        threadTask.doNotify();
        threadTask.donotifyAll();
        System.out.println(t1.getName() + "  stateName :" + t1.getState());
    }

Thread-0  stateName :WAITING
join
park()

调用 LockSupport.park() 方法,当前线程会阻塞,线程的状态会从 RUNNABLE 转换到 WAITING。调用 LockSupport.unpark(Thread thread) 可唤醒目标线程,目标线程的状态又会从 WAITING 状态转换到 RUNNABLE。

public static class ThreadTask implements Runnable {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + " 执行前");
            LockSupport.park();
            System.out.println(Thread.currentThread().getName() + " 执行后");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ThreadTask threadTask = new ThreadTask();
        Thread t1 = new Thread(threadTask);
        t1.start();
        TimeUnit.SECONDS.sleep(3);
        System.out.println(t1.getName() + "  stateName :" + t1.getState());
        LockSupport.unpark(t1);
        TimeUnit.SECONDS.sleep(3);
        System.out.println(t1.getName() + "  stateName :" + t1.getState());
    }
Thread-0 执行前
Thread-0  stateName :WAITING
Thread-0 执行后
Thread-0  stateName :TERMINATED

TIMED_WAITING

超时的sleep
public static class ThreadTask implements Runnable {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + " 执行前");
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " 执行后");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ThreadTask threadTask = new ThreadTask();
        Thread t1 = new Thread(threadTask);
        t1.start();
        TimeUnit.SECONDS.sleep(3);
        System.out.println(t1.getName() + "  stateName :" + t1.getState());
    }
Thread-0 执行前
Thread-0  stateName :TIMED_WAITING
Thread-0 执行后

面试问题

一个线程两次调用 start() 方法会出现什么情况?

抛出异常,IllegalMonitorStateException 不可以被start() 两次

        if (threadStatus != 0)
            throw new IllegalThreadStateException();

BLOCKED与WAITING的区别

blocked其实是线程在等待获取锁 获取失败后,被动触发的状态,会在此尝试获取锁,会自动唤醒。
WAITING是属于人为的主动触发的行为,线程等待其他线程发来的通知(notify\ notifyAll \ unpark()) 收到通知后,可能会顺序向后执行(RUNNABLE),也可能会再次获取锁,进而被阻塞住(BLOCKED)。

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

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

相关文章

Sectigo dv通配符ssl证书

DV通配符SSL证书是数字证书中比较特别的一款,这款SSL数字证书能同时为多个域名网站提供安全加密服务,帮助个人或者企事业单位获得主流浏览器以及终端的认可,从而营造良好的互联网环境。今天就随SSL盾小编了解Sectigo旗下的DV通配符SSL证书。 …

【Linux基础】1. Linux 启动过程

文章目录 【 1. 内核的引导 】【 2. 运行init 】 运行级别 【 3. 系统初始化 】【 4. 建立终端 】【 5. 用户登录系统 】【 6. 图形模式与文字模式的切换方式 】【 7. Linux关机 】 Linux系统的启动过程分为 5个阶段: (1)内核的引导。 &#…

Android修改submodule的lib包名

一、正常使用submodule的流程 在指定路径下: git clone gitgit.youraddress.com:android-apps/taobao.git cd taobao/ git checkout develop git submoudle init git submodule update二、改名步骤 需求:将LibStat改为libStat 因为Linux对大小写敏感…

国家开放大学 河南开放大学形成性考核 平时作业 统一参考资料

试卷代号:1258 房屋建筑混凝土结构设计 参考试题 一、单项选择题(每小题2分,共计40分) 1.( )是将框架结构中的部分跨间布置剪力墙或把剪力墙结构的部分剪力墙抽掉改为框架承重。 A.梁板结构体系 B.框…

银行数据分析进阶篇:银行业零售贷款营销与风控平衡分析

上周和大家分享了银行外呼数据分析与客户精准营销的案例,得到很多朋友正向的反馈,今天再次给大家带来银行业零售贷款营销与风控平衡分析的案例,结构清晰,可直接复制套用,特地分析给大家! 本文主要分享作者分…

车载软件易受攻击,如何规避嵌入式软件漏洞

在汽车开发中,汽车网络安全至关重要,特别是现在汽车软件变得日益互联。阅读本文,了解如何预防汽车网络安全漏洞。 为什么汽车网络安全很重要? 如今,互联汽车的解决方案远不只有简单的从A点到B点。通过实时数据共享、应…

【数值计算方法】《工程数值计算Python教程》笔记

文章目录 [toc]第一章:绪论 1.1 1.1 1.1|数值计算在工程科学中的重要性 1.2 1.2 1.2|数值计算方法 1.3 1.3 1.3|程序设计盒图计算方法的选取减少运算次数避免相近的数相减 1.4 1.4 1.4|误差的来源、表示及传递误差的来源和分类模型误差观测误差截断误差舍入误差 误差…

力扣日记12.19-【二叉树篇】二叉搜索树中的搜索

力扣日记:【二叉树篇】二叉搜索树中的搜索 日期:2023.12.19 参考:代码随想录、力扣 700. 二叉搜索树中的搜索 题目描述 难度:简单 给定二叉搜索树(BST)的根节点 root 和一个整数值 val。 你需要在 BST 中…

微软在 Perforce Helix 核心服务器中发现4个安全漏洞

微软分析师在对Perforce Helix的游戏开发工作室产品进行安全审查时,发现为游戏、政府、军事和技术等部门广泛使用的源代码管理平台 Perforce Helix Core Server 存在四大漏洞,并于今年 8 月底向 Perforce 报告了这些漏洞,其中一个漏洞被评为严…

HarmonyOS应用开发实战—开箱即用的活动创建页面【ArkTS】【鸿蒙专栏-33】

一.HarmonyOS应用开发实战—开箱即用的个人主页页面【ArkTS】【鸿蒙专栏-32】 1.1 项目背景 HarmonyOS(鸿蒙操作系统)是华为公司推出的一种分布式操作系统。它被设计为一种全场景、全连接的操作系统,旨在实现在各种设备之间的无缝协同和共享,包括智能手机、平板电脑、智能…

MFC 窗口创建过程与消息处理

目录 钩子简介 代码编写 窗口创建过程分析 消息处理 钩子简介 介绍几个钩子函数,因为它们与窗口创建工程有关 安装钩子函数 HHOOK SetWindowsHookExA([in] int idHook,[in] HOOKPROC lpfn,[in] HINSTANCE hmod,[in] DWORD dwThreadId ); 参数说明…

Kafka 安装与部署

目录 Kafka 下载 (1)将 kafka_2.11-2.4.1.tgz 上传至 /opt/software/ (2)解压安装包至 /opt/module/ [huweihadoop101 ~]$ cd /opt/software/ [huweihadoop101 software]$ tar -zxvf kafka_2.11-2.4.1.tgz -C ../module/&#…

PB开发Windows服务方案

1、项目简介 ​ PB作为一门客户端开发语言,虽然官方并未提供标准的Windows服务开发方案,但使用PB开发Windows服务并非无法实现。自PB9开始,PB提供了PBNI接口,PB与C可以通过这个接口互相调用,而C可以开发Windows服务。…

Java智慧工地数字化云平台源码(SaaS模式)

智慧工地是智慧城市理念在建筑工程行业的具体体现,智慧工地解决方案是建立在高度信息化基础上一种支持人事物全面感知、施工技术全面智能、工作互通互联、信息协同共享、决策科学分析、风险智慧预控的新型信息化手段。围绕人、机、料、法、环等关键要素,…

【算法与数据结构】376、LeetCode摆动序列

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引,可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析:本题难点在于要考虑到不同序列的情况,具体来说要考虑一下几种特殊情况: 1、上…

python学习,2.简单的数据类型

1.了解数及运算 整数:1,2,3。 运算符:加减乘除,**(乘方) 浮点数:python将所有带小数点的数称为浮点数。 这一块和别的语言有些不一样, 像C,分为float,double&#x…

河南开放大学形成性考核 平时作业 统一参考资料

试卷代号:1288 现代管理原理 参考试题(开卷) 一、单项选择(下列选项中只有一个答案是准确的,请将其序号填入括号中。每小题2分,共20分) 1.“凡事预则立,不预则废”,说…

极简Windows本机下载安装启动zookeeper

1.下载zookeeper Apache Download Mirrors 注意!!!:安装的路径不要用中文 2.生成zoo.cfg文件 复制zookeeper的conf目录下的zoo_simple.cfg文件,并重命名为zoo.cfg 修改zoo.cfg文件中的路径(data,log…

Navicat 16最新操作

Navicat 16最新操作 1 知识小课堂1.1 Navicat 161.2 其他数据库连接工具 2 下载和安装2.1 下载2.2 安装 1 知识小课堂 1.1 Navicat 16 Navicat 16是一款功能强大的数据库管理工具,可以创建多个连接,方便管理不同类型的数据库,包括MySQL、Ora…

如何利用研发效能度量工具分析代码评审的效率、质量与瓶颈?

代码评审(Code Review)是保障代码质量中一个非常重要的环节,也是保证项目交付质量的关键一环。代码评审的开展对于产品质量提升、工程素养提升、研发团队的技术分享交流,或是完善团队代码规范,都能起到重要的促进作用。…