Java 入门指南:Java 并发编程 —— LockSupport 线程阻塞唤醒类

news2024/9/22 5:37:16

LockSupport

LockSupport 是Java并发包中用于线程阻塞和唤醒的工具类。它提供了一种基于线程的阻塞和唤醒机制,类似于 Object 类中的 wait()notify() 方法,但与 wait()notify() 方法相比,LockSupport,它不依赖于对象的监视器锁,并且可以在任何地方对线程进行阻塞和唤醒操作。

主要方法

LockSupport 类的主要方法有:

  • park(): 当前线程阻塞,进入等待状态,直到被其他线程唤醒或被中断。

  • park(Object blocker): 当前线程阻塞,并关联一个对象,用于识别阻塞原因。

  • unpark(Thread thread): 唤醒指定的线程,如果线程之前没有被阻塞,则其后续 park() 方法会立即返回。

  • unpark(Object blocker): 唤醒与指定对象关联的线程,如果线程之前没有被阻塞,则其后续 park() 方法会立即返回。

特点

LockSupport 还具有以下特点:

  • 线程可以在任意顺序下执行 park()unpark() 方法,即使 unpark() 先于 park() 执行,阻塞的线程也不会错过唤醒信号。

  • LockSupport 提供的线程阻塞和唤醒是基于许可(permit)的。

    每个线程都有一个关联的许可,默认情况下是未授权的。调用 park() 方法会使用掉一个许可,调用 unpark() 方法会授予一个许可。

    如果线程在阻塞之前已经拥有一个许可,那么它在后续的 park() 方法调用时不会被阻塞。

  • LockSupport 提供了对线程中断的响应。如果线程在调用 park() 方法之前已经被中断,则 park() 方法会立即返回。

LockSupport 实现线程间的同步

假设我们有一个生产者线程和一个消费者线程,它们通过一个缓冲区进行通信。生产者将数据放入缓冲区,消费者从缓冲区读取数据。为了实现同步,我们使用 LockSupport 来控制线程的阻塞和唤醒。

import java.util.concurrent.locks.LockSupport;

public class LockSupportExample {

    private static final Object buffer = new Object();
    private static volatile boolean hasData = false;

    public static void main(String[] args) {
        Thread producer = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                synchronized (buffer) {
                    while (hasData) {
                        LockSupport.park();
                    }
                    hasData = true;
                    System.out.println("Produced: " + i);
                    LockSupport.unpark(Thread.currentThread());
                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        });

        Thread consumer = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                synchronized (buffer) {
                    while (!hasData) {
                        LockSupport.park();
                    }
                    hasData = false;
                    System.out.println("Consumed: " + i);
                    LockSupport.unpark(Thread.currentThread());
                }
                try {
                    Thread.sleep(1500);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        });

        producer.start();
        consumer.start();
    }
}

示例说明:

  • 生产者线程

    • 当缓冲区中有数据时,生产者线程通过 LockSupport.park() 进入等待状态。
    • 当消费者线程从缓冲区取走数据后,通过 LockSupport.unpark() 唤醒生产者线程。
  • 消费者线程

    • 当缓冲区中没有数据时,消费者线程通过 LockSupport.park() 进入等待状态。
    • 当生产者线程放入数据后,通过 LockSupport.unpark() 唤醒消费者线程。
  • 同步控制

    • 使用 synchronized 语句块来确保对 bufferhasData 的访问是同步的。
    • 通过 LockSupportparkunpark 方法来控制线程的阻塞和唤醒。

Dump 线程

在Java中,Dump线程 通常指的是生成线程转储(Thread Dump)的过程。线程转储是指捕获应用程序在某一时刻的所有线程的状态信息,包括线程ID、线程名称、当前执行的位置(堆栈跟踪)、锁信息等。线程转储对于诊断Java应用程序中的死锁、挂起或其他并发问题非常有用。

线程转储中包括着如以下的一些信息:

  • 线程 ID 和名称:线程的唯一标识符和可读名称。

  • 线程状态:线程的当前状态,例如运行(RUNNABLE)、等待(WAITING)、睡眠(TIMED_WAITING)或阻塞(BLOCKED)。

  • 调用堆栈:线程的调用堆栈跟踪,显示线程从当前执行点回溯到初始调用的完整方法调用序列。

  • 锁信息:如果线程正在等待或持有锁,线程转储通常还包括有关这些锁的信息。

生成线程转储

生成线程转储有多种方法,以下是几种常用的方法:

  1. 使用 jstack 命令

jstack 是JDK自带的一个命令行工具,用于生成线程转储。

jstack <pid>

其中 <pid> 是Java进程的PID。如果不知道PID,可以使用如下命令来查找:

jps
  1. 使用 Thread.dumpStack() 方法

在Java代码中,可以使用 Thread.dumpStack() 方法生成线程转储。但是这种方法通常不推荐在生产环境中使用,因为它会强制打印当前线程的堆栈跟踪,可能会干扰正常的程序执行。

public class ThreadDump {
    public static void main(String[] args) {
        Thread.dumpStack();
    }
}
  1. 使用 ManagementFactory API

Java Management Extensions (JMX) 提供了 ManagementFactory API,可以用来生成线程转储。

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;
import java.util.List;

public class ThreadDumpUsingAPI {
    public static void main(String[] args) {
        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
        long[] threadIds = threadMXBean.getAllThreadIds();
        List<ThreadInfo> threadInfos = threadMXBean.getThreadInfo(threadIds);

        for (ThreadInfo info : threadInfos) {
            System.out.println(info);
        }
    }
}
LockSupport 观察线程转储

使用 LockSupport 阻塞一个线程,并且之后通过 IntelliJ IDEA 查看线程的堆栈信息(即所谓的线程转储),可以按照下面的步骤来做:

  1. 编写代码以使用 LockSupport 阻塞线程: 你可以创建一个简单的 Java 应用,在其中使用 LockSupport.park() 方法来阻塞某个线程。

![[Pasted image 20240902223249.png]]

  1. 启动应用并让线程阻塞: 启动应用,并确保线程进入了阻塞状态。

  2. 在 IntelliJ IDEA 中生成线程转储: 当线程处于阻塞状态时,打开 IntelliJ IDEA 并连接到正在运行的应用(如果它不是一个 IntelliJ IDEA 内部启动的进程,则需要附加到该进程)。之后,在 Run 面板中点击「attach debugger

![[Pasted image 20240902223401.png]]

  1. 然后在 debugger 面板中右键选择「export thread

![[Pasted image 20240902223530.png]]

  1. 之后就可看到 Dump 线程信息了

在这里插入图片描述

分析线程转储

线程转储可以帮助开发者或运维人员快速定位以下问题:

  1. 死锁(Deadlock):多个线程互相持有对方所需的锁,导致无法继续执行。
  2. 挂起(Hang):某个线程似乎卡住了,长时间没有进展。
  3. 性能瓶颈:某些线程占用过多CPU资源,导致整体性能下降。
  4. 资源泄露:线程没有正确关闭或释放资源,导致资源泄露。

生成线程转储后,可以通过以下步骤来分析线程的状态:

  1. 查看线程状态:线程转储会显示每个线程的状态(如 RUNNABLEWAITINGTIMED_WAITINGBLOCKED 等)。
  2. 检查锁信息:如果存在锁争用,线程转储会显示锁的持有者和等待者。
  3. 分析堆栈跟踪:查看线程当前执行的位置,判断是否有死循环或长时间阻塞的情况。
  4. 识别资源泄露:检查是否有线程长期未结束,可能导致资源泄露。

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

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

相关文章

SpringBoot2:配置绑定与自动配置功能源码解读

一、配置绑定 1、作用说明 我们在开发springboot项目时&#xff0c;会有个配置文件&#xff0c;application.properties文件。 我们知道&#xff0c;像什么访问端口、上传功能的相关配置&#xff0c;都会在这里进行配置。 而这些&#xff0c;都是springboot自带的或者第三方j…

储能电站变流器设计与仿真研究(文章复现matlab)

为了有效解决交流子网与直流子网间的功率传输&#xff0c; 降低电流谐波&#xff0c; 基于三相电压源型变流器及变流器的控制方法&#xff0c; 在 MATLAB R2018a 环境下搭建了储能变流器的整体仿真模型。 电路主要由三相电网、 三相 PWM 变流器、Buck/Boost 变换器和蓄电池构成…

MQTT - EMQX安装使用

阅读本文前可先参考&#xff1a; MQTT - 消息队列遥测传输协议 MQTT&#xff08;Message Queuing Telemetry Transport&#xff09;是一种轻量级、基于发布-订阅模式的消息传输协议&#xff0c;适用于资源受限的设备和低带宽、高延迟或不稳定的网络环境。它在物联网应用中广受…

【html】新建一个html并且在浏览器运行

以下是一个简单的 HTML 小项目&#xff0c;展示一个包含标题、按钮和点击按钮后弹出提示框的基本页面 <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta name"viewport" content"widthde…

视频提取字幕的软件有哪些?高效转录用这些

探索视频的奥秘&#xff0c;从字幕开始&#xff01;你是否曾被繁复的字幕处理困扰&#xff0c;渴望有一款简单好用的在线免费软件来轻松解锁字幕提取&#xff1f; 告别手动输入的烦恼&#xff0c;我们为你精选了6款视频字幕提取在线免费软件&#xff0c;它们不仅能一键转录&am…

新手常见错误:Unable to find a @SpringBootConfiguration

目录 报错信息 &#xff1a; 1. 使用SpringBootTest注解 2. 使用ContextConfiguration注解 3. 检查包结构和注解&#xff08;一般都是这问题&#xff09; 4. 清理和重建项目 5. 检查依赖 报错信息 &#xff1a; Unable to find a SpringBootConfiguration, you need to use C…

pdf转word怎么转换?2024快速进行文件格式转换的几款软件

pdf转word怎么转换&#xff1f;2024快速进行文件格式转换的几款软件 将PDF文件转换为Word文档是日常工作中常见的需求&#xff0c;尤其是当你需要编辑或重新利用PDF中的内容时。市面上有许多软件可以帮助你轻松完成PDF转Word的任务&#xff0c;以下是五款值得推荐的软件&#…

WordPress 资源展示型下载类主题 CeoMax-Pro_v7.6 开心版

WordPress 资源展示型下载类主题 CeoMax-Pro_v7.6 开心版&#xff1b; CeoMax-Pro是一款极致美观强大的WordPress付费资源下载主题&#xff0c;它能满足您所有付费资源下载的业务需求&#xff01; 你的想法与业务不能被主题所限制&#xff01;CeoMax-Pro强大的功能&#xff0…

Spring Security 认证源码超详细分析

Spring Security 认证源码超详细分析 认证&#xff08;Authentication&#xff09;是系统确认用户信息的重要途径&#xff0c;用户通过认证之后&#xff0c;系统才能明确用户的身份&#xff0c;进而才可以为该用户分配一定的权限&#xff0c;这个过程也叫授权&#xff08;Auth…

智慧理财新纪元:蚂蚁集团“支小宝”智能理财助理深度体验与测评

2023年9月8日&#xff0c;蚂蚁集团宣布推出面向消费者的智能金融助理“支小宝2.0”&#xff0c;这是该公司首个基于金融大模型的应用产品。该产品在语言力、知识力、专业力和安全力方面展现出卓越性能&#xff0c;旨在为用户提供包括行情分析、持仓诊断、资产配置和投资教育陪伴…

MS SQL Server partition by 函数实战三 成绩排名

目录 需求 范例运行环境 视图样本设计 功能实现 基础数据展示 SQL语句 继续排序 小结 需求 假设有若干已更新考试成绩的考生&#xff0c;考试成绩包括总成绩、分项成绩1、分项成绩2&#xff0c;其它信息包括应聘岗位名称、姓名等信息。现希望根据总成绩计算排名&#…

C语言代码练习(第十一天)

今日练习&#xff1a; 25、用指针方法对10个整数按由大到小顺序排序 26、有一个班&#xff0c;3个学生&#xff0c;各学习4门课&#xff0c;计算总平均分数以及第 n 个学生的成绩 27、有一个3 * 4的二维数组&#xff0c;要求用指向元素的指针变量输出二维数组个元素的值。 用指…

mar3d模型文件问题

上一章使用mars3D模型库 遗留一个问题 部分资源不完整 如果模型没有其他依赖文件会正常加载 若有其他依赖就会报错 正常获取到的 缺少文件的 经过观察在gltf文件中发现缺失的是这几个文件 还是通过脚本下载 脚本实例 const fs require(fs); const path require(path); co…

Idea中修改Jsp文件的头部注释模版

文章目录 方法1&#xff0c;启动idea&#xff0c;单击“file”&#xff0c;选择“settings”2&#xff0c;选择Editor——File and Code Templates——other——Jsp files——jsp File.jsp。此时编辑如下图所示的右上区域即可修改模板。 每天学一个小技巧 方法 1&#xff0c;启…

FL Studio 24汉化破解版 v24.4.1.4285(附汉化破解补丁)

FL Studio 24.4.1.4285(汉化破解版是一款无比专业的音乐制作软件&#xff0c;它无论是在功能上还是用户界面都是在业内数一数二的。就拿它的用户界面来说&#xff0c;是目前同类软件中唯一做到100%矢量化&#xff0c;这样能更好地用在4K&#xff0c;5K甚至8K显示器上&#xff0…

力扣面试经典算法150题:Z 字形变换

Z 字形变换 今天的题目是力扣面试经典150题中的数组的中等难度题&#xff1a; Z 字形变换。 题目链接&#xff1a;https://leetcode.cn/problems/zigzag-conversion/description/?envTypestudy-plan-v2&envIdtop-interview-150 题目描述 将一个给定字符串 s 根据给定的行…

Jmeter 的 jar 包开发环境搭建

01 JDK环境变量配置 JAVA_HOMEE:\Program Files\Java\jdk1.8.0_102 Path%JAVA_HOME%\bin; CLASSPATH.;%JAVA_HOME%\lib\dt.jar;.;%JAVA_HOME%\lib\tools.jar 验证环境变量有没有生效&#xff1a;看到如下信息说明 JDK 环境变量已经生效 02 配置 maven 环境 1、下载地址&…

js中数组的定义及使用

数组的定义 Array 存储按位存储&#xff0c;紧密结构,在数组中查找元素&#xff0c;就必须要遍历数组&#xff0c;查找速度慢。 优点可以根据当前元素找到前一个或者后一个元素&#xff0c;可以排序 数组引用对象的是强引用&#xff0c;存储的是她的引用地址 length属性可读可…

TF | SD 卡出现无法删除的文件,乱码文件该如何处理 macOS

TF | SD 卡出现无法删除的文件&#xff0c;乱码文件该如何处理 macOS 一、问题描述 最近手头有张用在 Miyoo 掌机上的游戏 TF 卡&#xff0c;在macOS 系统下在回收站中出现了几个特殊文件名的文件&#xff0c;始终无法删除。 二、试着解决 我试过了网上的所有方法都无法删除…

rv1126-rv1109-mkcramfs-mkfs.cramfs-打包文件系统

事情是这样的: 定制了文件系统打包功能;然后我是根据这个指令 fakeroot mkfs.cramfs rootfs_glibc_rv1126/ rootfs.img mkfs.cramfs rootfs_glibc_rv1126/ rootfs.img 起因就是这个fakeroot; 不加的话打出来的rootfs.img是没有用户权限的 然后我根据fakeroot mkfs.cramfs ro…