掌握并发控制的“急刹车”艺术!

当一个线程运行时,另外一个线程可以直接通过interrupt方法对其设置中断标志位。

判断线程是否中断的2个方法:

// 判断目标线程是否被中断,不会清除中断标记。
Thread.currentThread().isInterrupted()
// 判断目标线程是否被中断,会清除中断标记
Thread.interrupted()

示例1:判断目标线程是否被中断,不会清除中断标记

public class Task2 implements Runnable {@Overridepublic void run() {System.out.println("线程的run方法开始执行");// 判断线程是否被中断,不会清除中断标记if (Thread.currentThread().isInterrupted()) {System.out.println("线程被中断");}if (!Thread.currentThread().isInterrupted()) {// 因为上面的Thread.currentThread().isInterrupted()不会清除中断标记// 因此线程保留了中断标记,所以该循环不会执行,程序不会输出1-3的数字for (int i = 0; i < 3; i++) {System.out.println("线程运行,i=" + i);}}System.out.println("线程的run方法执行结束");}
}运行上面的测试类Task2InterruptTest,程序运行结果:
线程的run方法开始执行
线程被中断
线程的run方法执行结束

以上的程序说明,Thread.currentThread().isInterrupted()不会清除中断标记,因此线程保留了中断标记,所以该循环不会执行,程序不会输出1-3的数字。

示例2:判断目标线程是否被中断,清除中断标记

public class Task3 implements Runnable {@Overridepublic void run() {System.out.println("线程的run方法开始执行");// 判断线程是否被中断,会清除中断标记if (Thread.interrupted()) {System.out.println("线程被中断");}if (!Thread.currentThread().isInterrupted()) {// 因为上面的Thread.interrupted()会清除中断标记// 因此线程的中断标记没有了,线程继续执行,程序会输出1-3的数字for (int i = 0; i < 3; i++) {System.out.println("线程运行,i=" + i);}}System.out.println("线程的run方法执行结束");}
}// 测试类
public class Task3InterruptTest {public static void main(String[] args) {Task3 task = new Task3();Thread thread = new Thread(task);thread.start();thread.interrupt(); // 中断thread线程的执行}
}程序运行结果:
线程的run方法开始执行
线程被中断
线程运行,i=0
线程运行,i=1
线程运行,i=2
线程的run方法执行结束

以上的程序说明,Thread.interrupted()会清除中断标记,thread线程没有了中断标记,因此Thread.currentThread().isInterrupted()的结果为false,所以线程继续执行,程序会输出1-3的数字。

下面我们来看一下如果处于阻塞状态(调用了sleep、join等方法)的线程,被执行了中断操作,会有什么样的结果。

答案很明显,处于阻塞状态下的线程被执行了中断操作,会抛出中断异常InterruptedException。

示例3:处于阻塞状态的线程被执行中断操作的结果演示

public class Task4 implements Runnable {@Overridepublic void run() {System.out.println("线程的run方法开始执行");try {Thread.sleep(5000); // 线程休眠5秒System.out.println("线程完成5秒钟的休眠");} catch (InterruptedException e) {e.printStackTrace();}System.out.println("线程的run方法执行结束");}
}// 测试类
public class Task4InterruptTest {public static void main(String[] args) {Task4 task = new Task4();Thread thread = new Thread(task);thread.start();try {Thread.sleep(2000); // 主线程休眠2秒} catch (InterruptedException e) {e.printStackTrace();}thread.interrupt(); // 中断thread线程的执行}
}程序运行结果:
线程的run方法开始执行
java.lang.InterruptedException: sleep interruptedat java.lang.Thread.sleep(Native Method)at testThread.day3.Task4.run(Task4.java:8)at java.lang.Thread.run(Unknown Source)
线程的run方法执行结束

通过上面的程序可以看出,处于阻塞状态下的线程被执行了中断操作,会抛出中断异常InterruptedException,但是thread线程在捕获到异常后,输出了“线程的run方法执行结束”的文字,说明thread线程在接收到中断指令后,并没有中断线程的执行,而是继续向下执行。

通过以上的程序示例,我们可以得出一个结论,那就是线程在执行了中断指令后,其实是给线程发了一个中断信号,线程被打上中断标记,如果线程没有对中断标记进行判断,做相应的处理,那么线程默认会继续执行,直到线程操作结束。

那么,问题来了,处于阻塞状态的线程被执行中断指令后,如何做到线程的中断呢,请看以下的代码。

示例4:处于阻塞状态的线程被执行中断指令后,立即把线程中断

public class Task5 implements Runnable {@Overridepublic void run() {System.out.println("线程的run方法开始执行");try {Thread.sleep(5000); // 线程休眠5秒System.out.println("线程完成5秒钟的休眠");} catch (InterruptedException e) {// 在catch块里进行处理,再次调用interrupt方法,线程是否会中断执行呢?System.out.println("线程被中断");Thread.currentThread().interrupt();}for (int i = 0; i < 3; i++) {System.out.println(i);}System.out.println("线程的run方法执行结束");}
}// 测试类
public class Task5InterruptTest {public static void main(String[] args) {Task5 task = new Task5();Thread thread = new Thread(task);thread.start();try {Thread.sleep(2000); // 主线程休眠2秒} catch (InterruptedException e) {e.printStackTrace();}thread.interrupt(); // 中断thread线程的执行}
}程序运行结果
线程的run方法开始执行
线程被中断
0
1
2
线程的run方法执行结束

通过上面的程序,大家会感到奇怪,明明已经在catch块里,又调用了Thread.currentThread().interrupt()方法,但是线程还是没有中断,继续往下执行。

在这里再一次和大家要强调说明的就是,调用线程的interrupt()方法,不是说线程就不执行了,而是向线程发出了中断信号,线程被打上中断标记,如果想让线程中断,必须在run方法里对中断信号进行响应,让程序return返回到被调用处,才能使线程真正的中断。

示例5:正确的让线程中断的例子

public class Task6 implements Runnable {@Overridepublic void run() {System.out.println("线程的run方法开始执行");try {Thread.sleep(5000); // 线程休眠5秒System.out.println("线程完成5秒钟的休眠");} catch (InterruptedException e) {// 在catch块里进行处理,让程序返回被调用处System.out.println("线程被中断");return;}for (int i = 0; i < 3; i++) {System.out.println(i);}System.out.println("线程的run方法执行结束");}
}// 测试类
public class Task6InterruptTest {public static void main(String[] args) {Task6 task = new Task6();Thread thread = new Thread(task);thread.start();try {Thread.sleep(2000); // 主线程休眠2秒} catch (InterruptedException e) {e.printStackTrace();}thread.interrupt(); // 中断thread线程的执行}
}程序运行结果:
线程的run方法开始执行
线程被中断

通过上面的程序,可以看出,使用return可以做到中断线程。

线程的中断其实是为了优雅的停止线程的运行,为了不使用stop方法而设置的。因为JDK不推荐使用stop方法进行线程的停止,因为stop方法会释放锁并强制终止线程,会造成执行一半的线程终止,带来数据的不一致性。

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

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

相关文章

【职业教育培训机构小程序】教培机构“招生+教学”有效解决方案

教培机构“招生教学”有效解决方案在数字化转型的浪潮中&#xff0c;职业教育培训机构面临着提升教学效率、拓宽招生渠道、增强学员互动等多重挑战。小程序作为一种新兴的移动应用平台&#xff0c;为解决这些痛点提供了有效途径。 一、职业教育培训机构小程序的核心功能 &…

Laravel 图片添加水印

和这个配合使用 Laravel ThinkPhP 海报生成_laravel 制作海报-CSDN博客 代码 //水印 $x_length $imageInfo[0]; $y_length $imageInfo[1];$color imagecolorallocatealpha($posterImage, 255, 255, 255, 70); // 增加透明度参数alpha$font_size 40; //字体大小 $angle …

HTML静态网页成品作业(HTML+CSS)——家乡沅陵介绍网页(1个页面)

&#x1f389;不定期分享源码&#xff0c;关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 &#x1f3f7;️本套采用HTMLCSS&#xff0c;未使用Javacsript代码&#xff0c;共有1个页面。 二、作品演示 三、代…

条款9:利用destructors避免泄露资源

对指针说拜拜。承认吧&#xff0c;你从未真正喜欢过它&#xff0c;对不&#xff1f; 好&#xff0c;你不需要对所有指针说拜拜&#xff0c;但是你真的得对那些用来操控局部性资源(local resources&#xff09;的指针说莎唷娜拉了。 举个例子&#xff0c;你正在为“小动物收养…

Flutter 中的 CircularProgressIndicator 小部件:全面指南

Flutter 中的 CircularProgressIndicator 小部件&#xff1a;全面指南 在 Flutter 应用开发中&#xff0c;加载指示器是提供用户反馈的重要组成部分&#xff0c;特别是在需要等待数据加载的场景中。CircularProgressIndicator 是 Flutter 提供的一个表现圆形加载动画的小部件。…

Python进阶:探索Python标准库和第三方库

在前两篇文章中,我们介绍了Python的基本语法和面向对象编程。在这篇文章中,我们将深入探索Python的标准库以及一些常用的第三方库。Python的强大之处不仅在于其简洁的语法,还在于丰富的库生态系统。通过使用这些库,你可以更高效地完成各种任务,从文件操作到数据分析、网络…

godot4.2 + GDextension c++在 vs code 中断点调试配置

游戏开发中如果做不到自己编写的代码做断点调试&#xff0c;无不是瞎子摸象&#xff0c;特别是C这么底层的语言。这2天开始在VS studio中折腾&#xff0c;一直折腾不出结果&#xff0c;几次想要放弃GODOT。最终今天在VS code中搞定了这断点调试C代码。 在上一篇文章我已经做好了…

React hooks - useContext

useContext 用法使用以非侵入的方式使用 Context使用 useContext 重构 useReducer 案例 用法 实现多层组件的数据传递 在全局创建 Context 对象在父组件中使用 Context.Provider 提供数据在子组件中使用 useContext 使用数据 import React, { useContext } from react // 全局…

全网爆火Remini 粘土滤镜风格,我用ComfyUI一键生成了(保姆级教程)!

一、火爆全网的Remini&#xff01; Remini真的火爆了&#xff01;最近大家的朋友应该都被粘土滤镜刷屏了。 小红书上粘土滤镜、粘土特效的帖子动不动就是几百万浏览量&#xff0c;几千赞。 在有些电商平台上还有人接单&#xff0c;帮忙定制remini粘土风格的照片&#xff01; …

解释浏览器缓存和本地存储的区别,以及如何实现事件的防抖和节流

1:浏览器缓存和本地存储的区别: 浏览器缓存:浏览器缓存是一种临时性的数据存储,用于提高网页加载速度。缓存的数据存储在内存或磁盘中,当用户再次访问相同的资源时,浏览器会优先从缓存中读取数据,而不是从服务器重新请求。缓存的数据可以在浏览器关闭后自动清除,或者根据 HTT…

vue+three.js实现3d系统的搭建

1.首先node.js是12.22版本的&#xff0c;安装three.js可以参考这篇文章 直接用Threejs入门-安装教程_安装three.js-CSDN博客 直接在终端安装three.js即可 npm install --save three 在相同目录下安装vite构建工具 npm install --save-dev vite 在项目里面看package.json中…

神秘顾客调查:第三方渠道监测如何操作?

第三方渠道监测是指通过专业的第三方机构或服务商&#xff0c;对企业的销售渠道进行系统化的监督和评估。这种监测帮助企业了解各渠道的表现&#xff0c;确保合规性&#xff0c;提升市场竞争力。深圳神秘顾客市场调查限公司&#xff08;SMS&#xff09;总结了第三方渠道监测的操…

【安装笔记-20240528-Linux-在 Vultr 云服务器上安装 OpenWRT】

安装笔记-系列文章目录 安装笔记-20240528-Linux-在 Vultr 云服务器上安装测试 OpenWRT 文章目录 安装笔记-系列文章目录安装笔记-20240528-Linux-在 Vultr 云服务器上安装测试 OpenWRT 前言一、软件介绍名称&#xff1a;OpenWRT主页官方介绍 二、安装步骤测试版本&#xff1a…

多function-calling 调用

多function-calling 调用 接上一篇function-calling调用&#xff0c;本篇实现了一个多function-calling的调用。OpenAI会根据function的描述自己来判断应该调用哪个function。最终调用function的动作是由我们来决定的&#xff0c;当然你也可以不调对应的函数。 两个函数分别是…

案例研究|MeterSphere助力万物云构建高效自动化测试平台

万物云空间科技服务股份有限公司&#xff08;以下简称为“万物云”&#xff09;&#xff0c;前身为万科物业发展股份有限公司&#xff0c;是国内领先的物管龙头上市公司。作为一家科技引领的全域空间服务商&#xff0c;万物云致力于打造产业级共享服务平台&#xff0c;基于空间…

1. lambda初体验

首先声明一个函数式接口&#xff0c;就只接口内只有一个抽象方法 //函数式接口 public interface Factory {Object getObject();}接口实现类 public class SubClass implements Factory {Overridepublic Object getObject() {return new User();}}User类 public class User …

酒店提前线上订房小程序源码系统 PHP+MySQL组合开发 源码开源可二开 带完整的安装代码包以及搭建教程

系统概述 随着移动互联网的普及&#xff0c;越来越多的人习惯通过手机进行酒店预订。传统的线下订房方式逐渐无法满足用户的需求&#xff0c;酒店提前线上订房小程序的出现成为必然趋势。该源码系统的开发旨在为酒店提供一个便捷、高效的线上订房平台&#xff0c;提升用户体验…

基于微信小程序+ JAVA后端实现的【医院挂号预约系统】 设计与实现 (内附设计LW + PPT+ 源码+ 演示视频 下载)

项目名称 项目名称&#xff1a; 《基于微信小程序的医院挂号预约系统设计与实现》 项目技术栈 该项目采用了以下核心技术栈&#xff1a; 后端框架/库&#xff1a; Java, SSM框架数据库&#xff1a; MySQL前端技术&#xff1a; 微信小程序, uni-app 项目展示 全文概括 本…

设置单群聊消息扩展

根据消息 ID &#xff0c;对单聊会话或群聊会话中已经发送的消息设置扩展信息。每次最多可以设置 100 个扩展属性信息&#xff0c;最多可设置 300 个。 通过 Server API 操作消息扩展&#xff0c;默认不会向操作者的客户端同步&#xff0c;会导致扩展信息不一致。如有需要&…

MySQL触发器实战:自动执行的秘密

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 &#x1f38f;&#xff1a;你只管努力&#xff0c;剩下的交给时间 &#x1f3e0; &#xff1a;小破站 MySQL触发器实战&#xff1a;自动执行的秘密 前言触发器的定义和作用触发器的定义和作用触发器的…