【JUC2022】第三章 线程中断与 LockSupport
【JUC2022】第三章 线程中断与 LockSupport
文章目录
- 【JUC2022】第三章 线程中断与 LockSupport
- 一、线程中断
- 1.什么是中断机制
- 2.中断 API
- 3.代码实现
- 4.Thread.sleep()
- 二、LockSupport
- 1.什么是 LockSupport
- 2.代码实现
- 3.总结
一、线程中断
1.什么是中断机制
首先,一个线程不应该由其他线程来强制中断或停止,而是应该由线程自己停止,自己来决定自己的命运。所以,Thread.stop,Thread.suspend,Thread.resume 都已经被废弃了
其次,在 Java 中没有办法立即停止一条线程,然而停止线程却尤为重要,如取消一个耗时操作。因此,Java 提供了一种用于停止线程的协商机制——中断,也即中断标识协商机制
中断只是一种协商机制,Java 没有给中断增加任何语法,中断的过程完全需要程序员自己实现
若要中断一个线程,需要手动调用该线程的 interrupt 方法,该方法也仅仅是将线程对象的中断标识设成 true。接着你需要自己写代码不断地检测当前线程的标识位,如果为 true,表示别的线程请求这条线程中断,此时究竟该做什么需要自己写代码实现
每个线程对象中都有一个中断标识位,用于表示线程是否被中断。该标识位为 true 表示中断,为 false 表示未中断。通过调用线程对象的 interrupt 方法将该线程的标识位设置为 true,可以在别的线程中调用,也可以在自己的线程中调用
2.中断 API
public void interrupt()
设置线程的状态为 true,发起一个协商而不会立刻停止线程
如果该线程已经执行了 wait()、join()、sleep()方法,此时其他线程调用该线程的 interrupt() 方法,那么该线程将立即退出阻塞状态,并抛出 InterruptedException
public static boolean interrupted()
返回当前线程的中断状态,并将当前线程的中断标识位重新设置为 false
这里可能会有一点抽象,读者朋友可能会疑惑为什么要重新设置中断标识位为 false。我觉得这只是一个表述问题,因为这个方法的主要功能就是将线程的中断标识位设置为 false,而不是返回中断状态。我们会发现,如果没有这个方法,我们就没有其他方法去重置线程的中断标识位了
public boolean isInterrupted()
返回当前线程的中断标识位
3.代码实现
package com.sisyphus.Interrupt;import java.util.concurrent.TimeUnit;public class InterruptDemo {public static void main(String[] args) {Thread t1 = new Thread(()->{while(true){if (Thread.currentThread().isInterrupted()){System.out.println(Thread.currentThread().getName() + "线程被中断");break;}System.out.println("线程运行中...");}},"t1");t1.start();//暂停try{TimeUnit.MILLISECONDS.sleep(20);}catch (InterruptedException e){e.printStackTrace();}new Thread(()->{t1.interrupt();},"t2").start();}
}
4.Thread.sleep()
为什么 Thread.sleep() 要抛中断异常
为了让线程具备感知中断能力。不能让线程无感知地一直睡眠,总会有需要“叫醒”它的突发情况
为什么 interrupt() “叫醒了”线程后要清除中断标志位
为了让线程能够继续执行本该执行的代码。线程中往往会使用 if(!Thread.currentThread().isInterrupted()) 来达到判断线程是否在睡眠中被中断的目的
如果需要实现睡眠中被中断,就不继续执行 if 代码块怎么办
需要我们在 catch 代码块中手动调用 interrupt()
try {Thread.sleep(100);
} catch (InterruptedException e) {//中断标志已经被清除了// 手动中断本线程,将本线程打上中断信号。Thread.currentThread().interrupt();
}
// Thread.currentThread().isInterrupted():是否被中断了(是否有中断标志)
if(!Thread.currentThread().isInterrupted()) {//如果没有被中断,则处理业务doSomething();
}
二、LockSupport
1.什么是 LockSupport
java.util.concurrent.locks.LockSupport
定义:用于创建锁和其它同步类的基本线程阻塞原语
LockSupport 有 park() 和 unpark() 两个重要方法,其作用分别是阻塞线程和解除阻塞线程
3 种让线程等待和唤醒的方法
- 使用 Object 中的 wait() 和 notify()
- 使用 JUC 包中的 Condition 和 await() 和 signal()
- 使用 LockSupport 中的 park() 和 unpark()
方法1和方法2存在的限制:
- 线程先要获得并持有锁
- 必须先执行等待,才能执行唤醒
Permit
LockSupport 使用了一种名为 Permit(许可) 的概念来做到阻塞和唤醒线程,每个线程都有一个 Permit,与 Semaphore 不同的是,Permit 的累加上限是 1
2.代码实现
package com.sisyphus.LockSupport;import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;public class LockSupportDemo {public static void main(String[] args) {Thread t1 = new Thread(()->{System.out.println(Thread.currentThread().getName() + "\t -----come in");LockSupport.park();System.out.println(Thread.currentThread().getName() + "\t -----被唤醒");},"t1");t1.start();//暂停几秒钟线程try{TimeUnit.SECONDS.sleep(1);}catch (InterruptedException e){e.printStackTrace();}new Thread(()->{LockSupport.unpark(t1);System.out.println(Thread.currentThread().getName() + "\t -----发出通知");},"t2").start();}public static void lockUnlock() {Lock lock = new ReentrantLock();Condition condition = lock.newCondition();new Thread(()->{lock.lock();try{System.out.println(Thread.currentThread().getName() + "\t -----come in");condition.await();System.out.println(Thread.currentThread().getName() + "\t -----被唤醒");}catch (InterruptedException e){e.printStackTrace();}finally {lock.unlock();}},"t1").start();//暂停几秒钟线程try{TimeUnit.SECONDS.sleep(1);}catch (InterruptedException e){e.printStackTrace();}new Thread(()->{lock.lock();try{condition.signal();System.out.println(Thread.currentThread().getName() + "\t -----发出通知");}finally {lock.unlock();}},"t2").start();}public static void waitNotify() {Object objectLock = new Object();new Thread(()->{synchronized (objectLock){System.out.println(Thread.currentThread().getName() + "\t -----come in");try{objectLock.wait();}catch (InterruptedException e){e.printStackTrace();}System.out.println(Thread.currentThread().getName() + "\t -----被唤醒");}},"t1").start();//暂停几秒钟线程try{TimeUnit.SECONDS.sleep(1);}catch (InterruptedException e){e.printStackTrace();}new Thread(()->{synchronized (objectLock){objectLock.notify();System.out.println(Thread.currentThread().getName() + "\t -----发出通知");}},"t2").start();}
}
3.总结
LockSupport 是一个线程阻塞工具类,所有的方法都是静态方法,可以让线程在任意位置阻塞,阻塞之后也有对应的唤醒方法。归根结底,LockSupport 调用的是 Unsafe 中的 native 方法
当调用 park() 时
- 如果有凭证,则会直接消耗掉这个凭证,然后正常退出
- 如果没有凭证,就必须阻塞等待凭证可用
当调用 unpark() 时,会增加一个凭证,但最多只有一个,累加无效
因此,当连续调用 park() 时,线程必然阻塞,无论之前调用过多少次 unpark()
相关文章:
【JUC2022】第三章 线程中断与 LockSupport
【JUC2022】第三章 线程中断与 LockSupport 文章目录【JUC2022】第三章 线程中断与 LockSupport一、线程中断1.什么是中断机制2.中断 API3.代码实现4.Thread.sleep()二、LockSupport1.什么是 LockSupport2.代码实现3.总结一、线程中断 1.什么是中断机制 首先,一个…...
数据结构刷题(七):202快乐数、1两数之和、454四数相加II、15三数之和、18四树之和
1.快乐数题目链接思路:使用set,当set中出现相同元素时,返回false注意:while循环中语句顺序; 除数取余。解法:public boolean isHappy(int n){Set<Integer> res new HashSet<>();int[] arr ne…...
华为机试题:HJ80 整型数组合并(python)
文章目录知识点详解1、input():获取控制台(任意形式)的输入。输出均为字符串类型。 1.1、int(input()) 与 map(int, input().spilt()) 的区别 1.2、input() 与 list(input()) 的区别、及其相互转换方法2、print() :打印输出…...

spring boot——自定义依赖实现自动配置
需求 要实现的功能是:实现一个可以支持miniooss两种方式,上传下载文件的自定义依赖。其中还包括一些创建桶、删除桶、删除文件等功能,但是最主要的是实现自动配置。 如果对spring理解很深的话,自动配置这些东西很容易理解&#…...

QMap 判断是否value是否已经存在,结合Sleep函数测试
网上查了资料,基本说的都是通过.value判断是否已经之前的key值,但是尝试.了一下发现有.key的函数,对比着来就感觉这个函数是用来判断是否已经存在value值,于是开始百度也几乎没有找到相关资料,只好自己看官方文档&…...

vue后台管理系统项目-table选择多行数据分页列表、一键全选重置功能
table选择多行数据 功能介绍: 1.列表分页功能; 2.一键全选,选中列表所有数据; 3.全选,选中当前页数据; 4.重置,清除选中状态; 5.列表搜索查询; 效果: 1.列表分…...

论文解读 | [CVPR2019] 基于自适应文本区域表示的任意形状场景文本检测
目录 1 研究背景及意义 2 总体设计 3 方法论 3.1 自适应文本区域表示 3.2 文本建议 3.3 建议改进 4 损失函数 5 实验及结果 1 研究背景及意义 现有的场景文本检测方法使用固定点数的多边形来 表示文本区域。例如,水平文本使用2个点(左上/右下)表示文本区域&…...

2月编程语言排行榜谁还没有看?
近日,TIOBE公布了2023年2月编程语言排行榜,本月各个语言表现如何?谁又摘得桂冠?一起来看看吧! TIOBE 2月Top15编程语言: 详细榜单查看TIOBE官网 https://www.tiobe.com/tiobe-index/ 关注IT行业的小伙伴们…...

nginx.conf配置方法详细介绍
从前面的内容学习中,我们知道Nginx的核心配置文件默认是放在/usr/local/nginx/conf/nginx.conf,这一节,我们就来学习下nginx.conf的内容和基本配置方法。读取Nginx自带的Nginx配置文件,我们将其中的注释部分【学习一个技术点就是在…...

【微信小程序】一文带你吃透开发中的常用组件
写在前面 小程序中的组件也是由宿主环境提供的,开发者可以基于组件快速搭建出漂亮的页面结构。 官方把小程序的组件分为了9大类,分别是: 1.视图容器 2.基础内容 3.表单组件 4.导航组件 5.媒体组件 6.地图组件 7.画布组件 …...

Nginx 部署 Vue 项目以及 Vue 项目刷新出现 404 的问题(完整步骤)(亲测有效)
Nginx 部署 Vue 项目以及 Vue 项目刷新出现 404 的问题(完整步骤)(亲测有效) 1.流程步骤(本教程下载的是1.20.2版本,放在D盘) 1-1. 首先去官方下载 nginx ,然后在当前目录下创建ht…...

leaflet 加载geojson数据,随机显示不同颜色的circleMarker
第086个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+leaflet项目中加载geojson数据,随机显示不同颜色的circleMarker. 直接复制下面的 vue+leaflet源代码,操作2分钟即可运行实现效果 文章目录 示例效果配置方式示例源代码(共89行)相关API专栏目标示例效果 配置方式…...

UL grant的分配(LCP)
欢迎关注同名微信公众号“modem协议笔记”。 UE有UL data时,会发送BSR的告知网络侧自己详细的请求,期望网络能够如期下发UL grant,正常情况下网络侧会给UE足够的UL grant去发送UL data,整个过程都会比较顺利。UE收到UL grant后&a…...

真我air笔记本电脑怎么重装Win10系统?
真我air笔记本电脑怎么重装Win10系统?最近真我air笔记本电脑挺多用户购买的,因为这款电脑性价比比较高,适合学生和一些办公人员来使用。但是系统预制了Win11系统,有用户想要将系统重装到Win10来使用。那么如何去进行系统的重装呢&…...

【闲聊杂谈】深入剖析SpringCloud Alibaba之Nacos源码
Nacos核心功能点 服务注册 Nacos Client会通过发送REST请求的方式向Nacos Server注册自己的服务,提供自身的元数据,比如ip地址、端口等信息。Nacos Server接收到注册请求后,就会把这些元数据信息存储在一个双层的内存Map中; 服…...
MySQL删除或清空表内数据的方法
MySQL删除或清空表内数据的方法 一、使用MySQL清空表数据命令:truncate SQL语法为: truncate table 表名注意: truncate该命令会直接将数据表内数据清空;truncate该命令删除数据后会重置Identity(标识列、自增字段…...
Android 权限(二): 动态权限讲解
1. 前言 继上一篇文章说到Android权限汇总, 请移步笔者的文章Android 权限(一):权限大全_broadview_java的博客-CSDN博客_android 仅使用中允许权限 先要理清楚权限分类和定义,本篇文章继续说一下动态权限的申请和框架层的实现流程, 以及如何实现赋予系统应用默认的…...

【C++】2.类和对象(上)
1.面向过程和面向对象 C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。C是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。 2.类的引入…...

扬帆优配|3300点半日游!上证指数冲高回落;再迎重磅利好!
今天早盘,A股冲高回落,上证指数3300点得而复失,深证成指也于12000点无功而返。 盘面上,煤炭、钢铁、房地产、才智政务等板块涨幅居前,酿酒、酒店餐饮、日用化工、IT设备等板块跌幅居前。北上资金净流入7.77亿元。 房地…...

如何编写性能测试计划?一篇文章教你设计符合项目的性能测试计划
上篇文章,我们讲过性能测试计划,接下来我们就来讲讲如何设计符合项目的性能测试计划。到上篇为止,我们了解了性能测试计划中包含的内容,但是,这个颗粒度,我觉得作为一名测试经验不够丰富的性能工程师来说&a…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

HDFS分布式存储 zookeeper
hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架,允许使用简单的变成模型跨计算机对大型集群进行分布式处理(1.海量的数据存储 2.海量数据的计算)Hadoop核心组件 hdfs(分布式文件存储系统)&a…...
JavaScript 数据类型详解
JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型(Primitive) 和 对象类型(Object) 两大类,共 8 种(ES11): 一、原始类型(7种) 1. undefined 定…...

基于PHP的连锁酒店管理系统
有需要请加文章底部Q哦 可远程调试 基于PHP的连锁酒店管理系统 一 介绍 连锁酒店管理系统基于原生PHP开发,数据库mysql,前端bootstrap。系统角色分为用户和管理员。 技术栈 phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销 2 个人中…...
安卓基础(Java 和 Gradle 版本)
1. 设置项目的 JDK 版本 方法1:通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分,设置 Gradle JDK 方法2:通过 Settings File → Settings... (或 CtrlAltS)…...
怎么开发一个网络协议模块(C语言框架)之(六) ——通用对象池总结(核心)
+---------------------------+ | operEntryTbl[] | ← 操作对象池 (对象数组) +---------------------------+ | 0 | 1 | 2 | ... | N-1 | +---------------------------+↓ 初始化时全部加入 +------------------------+ +-------------------------+ | …...

解析“道作为序位生成器”的核心原理
解析“道作为序位生成器”的核心原理 以下完整展开道函数的零点调控机制,重点解析"道作为序位生成器"的核心原理与实现框架: 一、道函数的零点调控机制 1. 道作为序位生成器 道在认知坐标系$(x_{\text{物}}, y_{\text{意}}, z_{\text{文}}…...
Windows 下端口占用排查与释放全攻略
Windows 下端口占用排查与释放全攻略 在开发和运维过程中,经常会遇到端口被占用的问题(如 8080、3306 等常用端口)。本文将详细介绍如何通过命令行和图形化界面快速定位并释放被占用的端口,帮助你高效解决此类问题。 一、准…...

深入理解 C++ 左值右值、std::move 与函数重载中的参数传递
在 C 编程中,左值和右值的概念以及std::move的使用,常常让开发者感到困惑。特别是在函数重载场景下,如何合理利用这些特性来优化代码性能、确保语义正确,更是一个值得深入探讨的话题。 在开始之前,先提出几个问题&…...