正确理解线程WAITING状态

news2024/11/15 11:03:28

正确理解线程WAITING状态

今天来学习下,Java的线程状态,重点讨论下thread.state.WAITING。讨论下线程如何进入此状态,以及它们之间的区别。最后,我们进一步了解java.util.concurrent.locks.LockSupport,它提供了几种用于同步的静态实用方法。

线程状态

在JDK Thread源代码中存在一个内部枚举定义,它定义了Java 线程的各种状态

public enum State {
        // 新建状态
        NEW,
        //运行状态 包含操作系统就绪、运行两种状态
        RUNNABLE,
        //阻塞状态
        BLOCKED,
        //等待状态
        WAITING,
				//限时等待
        TIMED_WAITING,
        //终止状态
        TERMINATED;
    }

img

线程状态之间的转换如上图(图片来源于互联网)。

进入WAITING态

JDK内部提供多种方式让线程进入WAITING状态,如

Object.wait()

Java开发者将线程状态置于WAITING状态的最标准方法之一就是调用wait()方法。当线程拥有一个对象的monitor锁时,开发者可以通过调用wait()方法暂停该线程让;其他线程执行,当其他线程执行完毕后,调用notify()、notifyAll()方法唤醒被暂停的线程。暂停期间,线程处于WAITING状态,这会在线程的DUMP文件中体现出来。如下

"WAITING-THREAD" #11 prio=5 os_prio=0 tid=0x000000001d6ff800 nid=0x544 in Object.wait() [0x000000001de4f000]
   java.lang.Thread.State: WAITING (on object monitor)

Thread.join()

另一种让线程暂停的方式是调用 join方法。当主线程需要等待工作线程执行完毕才执行时,开发者在主线程中通过调用工作线程实例的join()方法。此时主线程将进入WAITING状态。可以使用jstack命令查看线程状态

"MAIN-THREAD" #12 prio=5 os_prio=0 tid=0x000000001da4f000 nid=0x25f4 in Object.wait() [0x000000001e28e000]
   java.lang.Thread.State: WAITING (on object monitor)

注意,Thread.join 有重载方法,开发者可以指定线程等待时间,无参的join方法表示一直等待

public final synchronized void join(final long millis)
    throws InterruptedException {
    ...
 }
//该方法表示等待 millis(毫秒) + nanos(纳秒) 的时间
 public final synchronized void join(long millis, int nanos)
    throws InterruptedException {
 		...
 }
public final void join() throws InterruptedException {
        join(0);
}

LockSupport.park()

最后,开发者也可以调用LockSupport的静态park()方法将线程置于WAITING状态。调用park()方法将停止当前线程执行,并且线程状态为WAITING。同样可以使用jstack命令查看线程状态

"PARKED-THREAD" #11 prio=5 os_prio=0 tid=0x000000001e226800 nid=0x43cc waiting on condition [0x000000001e95f000]
   java.lang.Thread.State: WAITING (parking)

LockSupport

如之前所述,最优雅的方式是通过LockSupport类的相关方法来暂停、启动线程。该类是Unsafe的包装类, 对线程的操作底层委托Unsafe。只是由于Unsafe被认为是一个内部Java API,开发者不应该直接使用。因此LockSupport是官方推荐操作线程的方式。实际上很多GUC(java.util .concurrent)下面的很多类底层也都使用了LockSupport。

基本使用

使用LockSupport停止线程的执行非常简单,开发者只需要调用park()方法即可。不必跟之前的方式一致,需要提供对线程对象本身的引用——代码会停止调用它的线程。示例代码如下:

package com.andy.spring.boot.docker.thread;

import java.util.concurrent.locks.LockSupport;

public class Application {
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            int acc = 0;
            for (int i = 1; i <= 100; i++) {
                acc += i;
            }
            System.out.println("Work finished");
            LockSupport.park();
            System.out.println(acc);
        });
        t.setName("PARK-THREAD");
        t.start();
    }
}

由于代码中调用了park()方法,工作线程暂停,因此程序永远不会退出。启动程序,接下来我们使用jstack命令看下线程的堆栈信息

#使用jcmd命令查看正在运行的java程序
AndydeMacBook-Pro:spring-boot-docker andy$ jcmd
57778 jdk.jcmd/sun.tools.jcmd.JCmd
57768 com.andy.spring.boot.docker.thread.Application
...
AndydeMacBook-Pro:spring-boot-docker andy$ 
# 根据上面的 pid(57768) 使用jstack查看堆栈信息
jstack 57768

在这里插入图片描述

如需要在工作线程执行完毕后,退出应用程序,也非常简单只需要在代码的最后加上 **LockSupport.unpark(t);**即可

t.setName("PARK-THREAD");
t.start();
// 停顿1秒是为了让工作线程有足够的时间执行
Thread.sleep(1000);
LockSupport.unpark(t);

底层原理

  • park API内部工作原理是使用单一许可,类似于唯一的一个信号量 - Semaphore。内部使用许可管理线程状态,park()方法使用需求,unpark()方法让许可重新生效
  • 由于每个线程只能生成一个许可,因此调用多次unpark()方法是没有意义的。任意一次调用park()方法就可以禁止线程。

方法重载

public static void park(Object blocker) {
        Thread t = Thread.currentThread();
        setBlocker(t, blocker);
        U.park(false, 0L);
        setBlocker(t, null);
    }

如上,LockSupport源码里面还有一个park的重载方法,方法包含一个blocker参数。该参数并不会影响线程的执行,但是会在线程的dump日志中体现出来,目的是便于开发者诊断并发问题。

//将之前的代码 稍作修改
String syncObj = "hello";
LockSupport.park(syncObj);

使用jstack命令重新抓取线程dump日志, 仔细观察,会发现多了一段报错日志

在这里插入图片描述

总结

  • Parking vs. Waiting 两种方式为开发者都提供了相似的功能,暂停线程。那么,在日常开发中如何使用呢?通常情况下LockSupport的相关类认为是低级的API,偏底层,需要使用者非常熟悉其原地和使用方式,否则滥用会造成难以理解的死锁。而且,绝大多数情况下,Thread类的 wait()、join()方法能够满足要求。

  • 使用parking的好处是,不需要同步代码块来禁用其他线程进入临界资源。这一点非常重要,因为同步代码块会产生 happens-before的现场,会强制刷新所有变量。极端情况下,可能会降低性能。因此需要慎重使用

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

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

相关文章

【分布式能源的选址与定容】基于非支配排序多目标遗传优化算法求解分布式能源的选址与定容(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…

AOP通知获取数据

之前说到了AOP可以对原始方法进行增强&#xff0c;那么AOP是否可以获取到原始方法的数据并对原始方法的数据利用增强方法进行处理呢&#xff1f;我们将从获取参数、获取返回值和获取异常三个方面来研究。 首先&#xff0c;我们可以知道&#xff0c;所有的通知类型都可以获取参数…

微服务框架 SpringCloud微服务架构 10 使用Docker 10.6 容器命令练习

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式&#xff0c;系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 SpringCloud微服务架构 文章目录微服务框架SpringCloud微服务架构10 使用Docker10.6 容器命令练习10.6.1 直接开干10 使用Docker 10.6 容器…

阿里“重推”的Spring+Boot+MVC+CloudAlibaba学习手册,开源下载

Spring框架自诞生以来一直备受开发者青睐&#xff0c;有人亲切的称之为&#xff1a;Spring 全家桶。Spring更是避免了重复造轮子的工作并跟随着互联网行业的发展做出不断的更新&#xff0c;很多研发人员把spring看作心目中最好的Java项目&#xff0c;没有之一。 可以毫不夸张的…

VS Code 扩展开发如何保持用户视觉体验一致

本文介绍如何在 VS Code 插件的 webview 中加载本地的资源文件&#xff0c;并如何使用 VS Code 自身的 UI 来实现用户视觉体验的一致。 背景 最近想做一个 VS Code 的插件用来简便我使用 VS Code 来编辑 Markdown 博客的体验&#xff0c;在设计插件的过程中&#xff0c;因为需…

计算机毕业论文Java项目源码下载S2SH智慧社区管理系统[包运行成功]

&#x1f496;&#x1f496;更多项目资源&#xff0c;最下方联系我们✨✨✨✨✨✨ 目录 Java项目介绍 资料获取 Java项目介绍 《基于S2SH实现的智慧社区管理系统》该项目采用技术jsp、strust2、Spring、hibernate、tomcat服务器、mysql数据库 &#xff0c;项目含有源码、答…

力扣hot100——第6天:32最长有效括号、33搜索旋转排序数组、34在排序数组中查找元素的第一个和最后一个位置

文章目录1.32最长有效括号1.1.题目1.2.解答2.33搜索旋转排序数组2.1.题目2.2.解答3.34在排序数组中查找元素的第一个和最后一个位置【代码随想录已刷】1.32最长有效括号 参考&#xff1a;力扣题目链接&#xff1b;题解1&#xff0c;题解2 1.1.题目 1.2.解答 这道题目官方的题…

FAT12文件系统

简介 FAT12文件系统是指&#xff1a;在磁盘上规定一种特定的存储格式&#xff0c;这种存储格式高效方便&#xff0c;功能强大&#xff0c;因此形成了统一的规定。 基础知识 具体来说FAT12文件系统为1.44M的软盘设计。1.44M的软盘有2880个扇区&#xff0c;一个扇区有512个字节&…

大数据下一代变革之必研究数据湖技术Hudi原理实战双管齐下-后续

文章目录集成Flink编程示例打包运行CDC入湖概述MySQL 启用 binlog初始化MySQL 源数据表准备Jar包依赖flink读取mysql binlog写入kafkaflink读取kafka数据并写入hudi数据湖调优MemoryParallelismCompaction集成Hive集成步骤Flink同步HiveHive Catalog集成Flink 编程示例 本节通…

[附源码]计算机毕业设计springboot右脑开发教育课程管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

微服务框架 SpringCloud微服务架构 10 使用Docker 10.4 容器命令案例1

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式&#xff0c;系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 SpringCloud微服务架构 文章目录微服务框架SpringCloud微服务架构10 使用Docker10.4 容器命令案例110.4.1 直接开干10.4.2 总结10 使用Docke…

03_openstack之项目及用户管理

目录 一、环境准备 二、项目管理 1、项目介绍 2、创建项目 三、用户管理 1、用户介绍 2、创建用户 一、环境准备 部署openstack私有云环境&#xff0c;步骤&#xff1a;02_openstack私有云部署_桂安俊kylinOS的博客-CSDN博客 以下操作均基于上述环境 二、项目管理 1、…

[附源码]计算机毕业设计springboot在线票务系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

基于采样的规划算法之RRT家族(三):RRT*

RRT算法是边随机产生节点边生长一棵路径树,当这棵树与目标点相遇,便从相遇点回溯到起点得到路径解。对于新产生的随机节点,原始RRT算法将路径树上距离它最近的节点作为它的父节点,并不能保证新节点通过该父节点就是最短路径。并且,就算新节点连接是最优的,也无法保证未来…

快速统计文本数字之和

实例需求&#xff1a;A列到F列为文本数据&#xff0c;每个单元格中包含3个数字&#xff0c;数字之间使用竖线分隔&#xff0c;现需要计算每个单元格中的数字之后。 例如F15单元格内容为10┃5┃18&#xff0c;则需要计算10、5、18三个数字之和&#xff0c;结果为33&#xff0c;…

【RTS】李宇翔 monibuca 讲座 学习

不解码,如何跳帧、追帧。启动工程,方便二次开发 按需引入引擎和插件流媒体应用 监控 : 物联网。转发 :用于会议,里面有很多会控逻辑,不同于流媒体本身。 起源于 FLASH视频会议 cs fms ams ,red5crtmpserver 很多问题 streaming服务器很难开发monaserver 基础上开发monib…

事业编招聘:新华社2023校园招聘正式启动

新华社是党中央一手创办和领导的新闻舆论机构&#xff0c;随着中国人民的革命事业和社会主义建设事业的发展而成长壮大&#xff0c;是一个具有光荣历史和优良传统作风的新闻机构。 新华社作为党中央喉舌、耳目、智库&#xff0c;是党的新闻舆论工作主力军、主渠道、主阵地。 …

【随笔记】分享一下26个常用的IDEA插件

文章目录1. Chinese Language2. Atom Material Icon3. Rainbow Brackets4. Translation5. Codota6. GenerateAllSetter7. GsonFormatPlus8. Alibaba Java Coding Guidelines9. Free Mybatis Tool10. maven-search11. Maven Helper12. CodeGlance Pro13. MyBatisCodeHelperPro14…

[附源码]计算机毕业设计学生在线考试系统Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

[附源码]计算机毕业设计颐养天年辅助平台Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…