【Java并发编程】 interrupt 方法详解

news2024/12/23 10:07:08

【Java并发编程】 interrupt 方法详解

文章目录

  • 【Java并发编程】 interrupt 方法详解
    • 1.介绍
    • 2.打断阻塞状态线程
    • 3.打断正常状态的线程
    • 4.两阶段终止模式
    • 5.打断 park 线程

1.介绍

程序中,有些线程的终端需要外部干预,比如有线程存在while(true)循环,或者一些阻塞操作,比如sleepwaitjoin等。

终端线程的方式,如果直接使用 stopsuspend等烦啊,对程序来说是不太严谨的,这些方法类似于直接杀死线程,可能会造成数据问题。

为了更好的解决这些问题,我们可以使用interrupt方法,调用该方法就相当于告诉线程你要被打断了,赶快准备结束你的线程,具体什么时候结束,你自己决定,我只是给你传个话。这种方式就比stop这种强行让你结束好多了。

2.打断阻塞状态线程

sleep,wait,join这几个方法都会让线程进入阻塞状态,该状态下,如果线程被打断,则会清空打断状态(被打断时为true),并抛出异常。以sleep为例:

public class Main {
    public static void main(String[] args) throws Exception {
        Thread t1 = new Thread(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "t1");
        t1.start();
        Thread.sleep(500);
        t1.interrupt();
      System.out.println(t1.isInterrupted());
    }
}

结果:打断标记为false,本来被打断后打断标记应该为true,但是因为当阻塞线程被打断后会抛出异常,并且清楚打断标记。 为啥会这样呢?

一个正在阻塞的线程被打断,因为该线程还在阻塞,不知道到底发生了什么,突然被打断就会抛异常来停止当前的阻塞状态,以应对外面发生的变化。也就是响应中断。

3.打断正常状态的线程

public class Main {
    public static void main(String[] args) throws Exception {
        Thread t1 = new Thread(() -> {
            while (true) {
                boolean interrupted = Thread.currentThread().isInterrupted();
                if (interrupted) {
                 	System.out.println("被打断");
                    break;
                }
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "t1");
        t1.start();
        Thread.sleep(500);
        t1.interrupt();
      System.out.println(t1.isInterrupted());
    }
}

我们通过运行结果可以发现,打断正常线程是打断标记会置为true,然后线程可以继续执行,所以就给了打断线程处理后事的时间,自己选择何时结束线程。这样做的目的是 对之前的线程的数据保存现场或者处理,如果直接中断就会出现很多问题,比如一个线程拿着锁(手动上锁下锁)突然被中断,那么该锁就一直不会被释放,其他线程就会一直等待,造成死锁。

4.两阶段终止模式

提出问题

如果在一个线程中“体面”的终止另一个线程,也就是给终止线程一个处理后事的机会。

错误的解决思路

1.使用stop方法终止线程

这种思路是错误的 因为Thread.stop()方法在结束线程时,会直接终止线程,并且会立即释放这个线程所有的锁,而这些锁恰恰是用来维持对象一致性的。如果此时,写入线程写入的数据正写到一半,并强行终止,那么对象就会被写坏,同时由于锁已经释放,另外一个等待该锁的线程就会顺理成章的对到了这个不一致的对象。

2.使用System.exit(int)方法终止线程

这个方法会让整个程序都停止,而我们的目的仅仅是停止一个线程

正确的解决思路

用interrupt方法,当陷入阻塞时 中断线程抛出异常 可以处理后事,当中断正常状态线程时 可以根据中断标记 来处理后事

public class TPTInterrupt {
    private Thread thread;

    public void start() {
        thread = new Thread(() -> {
            while (true) {
                Thread current = Thread.currentThread();
                if (current.isInterrupted()) {
                    System.out.println("料理后事");
                    break;
                }
                try {
                    Thread.sleep(1000);
                    System.out.println("保存数据");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    // 将打印标记置为true
                    current.interrupt();
                }
                // 执行监控操作
            }
        }, "监控线程");
        thread.start();
    }

    public void stop() {
        thread.interrupt();
    }
}

测试

public class TPTInterruptDemo {
    public static void main(String[] args) throws InterruptedException {
        TPTInterrupt t = new TPTInterrupt();
        t.start();

        Thread.sleep(3500);
        System.out.println("stop");
        t.stop();
    }
}

结果

保存数据
保存数据
保存数据
stop
料理后事
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at org.example.juc.TPTInterrupt.lambda$start$0(TPTInterrupt.java:19)
at java.lang.Thread.run(Thread.java:750)

如果线程正在正常执行,那么如果线程被打断,打断标志就为true,就可以处理后事了,如果线程正在阻塞状态,那么如果线程被打断,就需要再次打断该线程使标志为true,因为阻塞异常被打断会抛出异常并重置为false,这样才能给线程处理后事的机会并且知道线程在阻塞状态被打断了。

image-20230203175308038

5.打断 park 线程

**打断 park 线程,不会清空打断状态 **

public class parkDemo {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            System.out.println("park...");
            LockSupport.park();
            System.out.println("unpark...");
            System.out.println("打断状态: " + Thread.currentThread().isInterrupted());
        }, "t1");

        t1.start();

        Thread.sleep(500);
        t1.interrupt();
    }
}

结果

park...
unpark...
打断状态: true

如果打断标志已经是 true,则park会失效

public class parkDemo2 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                System.out.println("park...");
                LockSupport.park();
                System.out.println("打断状态: " + Thread.currentThread().isInterrupted());
            }

        }, "t1");

        t1.start();

        Thread.sleep(500);
        t1.interrupt();
    }
}

结果

park...
打断状态: true
park...
打断状态: true
park...
打断状态: true
park...
打断状态: true
park...
打断状态: true

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

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

相关文章

值得拥有并收藏的 3个安卓/鸿蒙手机解锁软件

手机无论支持哪种操作系统&#xff0c;都占据了每个人口袋里的空间。随着大量移动设备的使用&#xff0c;搜索引擎上也出现了同样数量的查询&#xff0c;其中最常见的是提供安卓/鸿蒙屏幕锁定删除工具。由于安卓是当今最畅销的设备&#xff0c;我们的首要任务是为您提供最好的安…

矿山安全生产监测预警系统 opencv

矿山安全生产监测预警系统通过pythonopencv网络模型计算机视觉技术&#xff0c;对现场画面中人的不安全行为”、“物的不安全状态”、“环境的不安全因素”三方面出发进行实时监测&#xff0c;当监测到现场画面中人员未穿反光衣行为、明火烟雾、未穿安全帽行为、矿车掉道识别、…

【王道数据结构】第三章 | 栈和队列

目录 一、栈stack 基本概念 基本操作 存储结构​​​​​​​ 二、队列Queue 基本概念 队列的基本操作 存储结构 三、栈的应用 栈在括号匹配中的应用 栈在表达式求值中的应用​编辑 栈在递归中的应用 一、栈stack 基本概念 只允许在一端(栈顶top)进行插入或删除操…

大数据看全国疫情生活,北京、武汉已过疫情拐点

自2022年11月末&#xff0c;很多地区新冠病例数据呈现下降趋势&#xff0c;与实际感知有明显差异。2022年12月14日&#xff0c;国家疾控中心发布消息&#xff0c;核酸检测实行“愿检尽检”&#xff0c;不再公布无症状感染者数据。因此&#xff0c;网友们想要了解所在地和老家的…

python能做的100件事04 - python解析PDF

1. python常用pdf库 名称特点PyPDF2已不再维护&#xff0c;继任者PyPDF4 ,但很长时间没有更新了,能读不能写pdfrw能读不能写&#xff0c;但可以兼容ReportLab写ReportLab商业版的开源版本&#xff0c;能写不能读pikepdf能读不能写pdfplumber能读不能写PyMuPDF读写均可,基于GPL…

Vue面试题2

1&#xff1a;vue.js的两个核心是什么&#xff1f; 答:数据驱动和组件化。 2&#xff1a;vue生命周期钩子函数有哪些&#xff1f; 答:总共分为8个阶段创建前/后&#xff0c;载入前/后&#xff0c;更新前/后&#xff0c;销毁前/后 3&#xff1a;第一次页面加载会触发哪几个钩子…

C语言二维数组中:主次对角线求和,上下三角求和,杨辉三角,矩阵转置

p8 有些的结论需要直接记住 目录 矩阵转置 主对角线和次对角线 下三角 和上三角&#xff08;一般是让求和&#xff09; 下三角 上三角 杨辉三角 矩阵转置 不是方阵 需要用到第二个二维数组 b[i][j]a[i][j] 是方阵 方法1 借助第二个二维数组&#xff0c;同上 方…

C++基础-3函数

一、函数 1.概述 作用&#xff1a;将一段经常使用的代码封装起来&#xff0c;减少重复代码 而一个较大的程序&#xff0c;一般分为若干个代码块&#xff0c;每个模块实现特定的功能 2.定义 5个内容&#xff1a; ①返回值类型 ②函数名 ③参数列表 ④函…

力扣刷题记录——1287. 有序数组中出现次数超过25%的元素、1299. 将每个元素替换为右侧最大元素 、1413. 逐步求和得到正数的最小值

本专栏主要记录力扣的刷题记录&#xff0c;备战蓝桥杯&#xff0c;供复盘和优化算法使用&#xff0c;也希望给大家带来帮助&#xff0c;博主是算法小白&#xff0c;希望各位大佬不要见笑&#xff0c;今天要分享的是——《力扣刷题记录——1287. 有序数组中出现次数超过25%的元素…

【vector的模拟实现】

目录 1 类的成员变量 2 常用成员函数和迭代器 3 增删查改 3.1 reverse 3.2 push_back 3.3 resize 3.4 insert && erase 4 默认成员函数 4.1 构造函数 4.2 拷贝构造 4.3 赋值运算符重载 4.4 析构函数 前面我们详细介绍了string类的使用&#xff0c;vector的…

关于 JSON 数据格式的完全使用指南

前言 本文将对 JSON 的语法、解析、序列化进行详细的说明&#xff0c;帮助大家掌握 JSON 的使用方式。 如果文中有不对、疑惑或者错字的地方&#xff0c;欢迎在评论区留言指正&#x1f33b; 一、JSON简介 在 JSON 之前&#xff0c;XML 曾经一度成为互联网上传输数据的事实标…

【论文阅读】【剪枝】Learning Efficient Convolutional Networks through Network Slimming

摘要 深度卷积神经网络&#xff08;CNN&#xff09;在许多实际应用中的部署在很大程度上受到其高计算成本的阻碍。在本文中&#xff0c;我们提出了一种新的神经网络学习方案&#xff0c;以同时1&#xff09;减小模型大小&#xff1b;2&#xff09; 减少运行时内存占用&…

Kali Linux- 社会工程及压力工具教程

在本章中&#xff0c;我们将了解 Kali Linux 中使用的社会工程工具。 文章目录社会工程Kali Linux - 压力工具SlowhttptestinvitefloodTHC-SSL-DOS总结社会工程 社会工程师工具包 &#xff08;SET&#xff09; 是一个专为社会工程设计的开源渗透测试框架。SET具有许多自定义攻…

第九章(12):STL之常用查找算法

文章目录前情回顾常用查找算法findfind_ifadjacent_findbinary_searchcountcount_if下一座石碑&#x1f389;welcome&#x1f389; ✒️博主介绍&#xff1a;一名大一的智能制造专业学生&#xff0c;在学习C/C的路上会越走越远&#xff0c;后面不定期更新有关C/C语法&#xff0…

读懂用户之用户调研怎么做?(内附模板教程)

随着互联网的发展&#xff0c;不管是做产品设计、运营&#xff0c;还是市场推广&#xff0c;我们都需要思考的是“用户真正想要的是什么&#xff1f;”。这时候&#xff0c;用户调研的重要性就凸显出来了。 一、什么是用户调研 用户调研&#xff0c;指通过各种方式得到受访者的…

Redis常用指令

3. 常用指令 在这部分中呢&#xff0c;我们家学习两个知识&#xff0c;第一个是key的常用指令&#xff0c;第二个是数据库的常用指令。和前面我们学数据类型做一下区分&#xff0c;前面你学的那些指令呢&#xff0c;都是针对某一个数据类型操作的&#xff0c;现在学的都是对所…

#14环形链表#

环形链表 1题目链接 链接 2思路 slow和fast指向链表的开始 slow一次走一步 fast一次走两步 不带环 fast就会为空 带环 fast就会在环里追上slow 3实现 bool hasCycle(struct ListNode* head) {struct ListNode* slow head, * fast head;while (fast && fast->ne…

微信小程序学习第3天——网络数据请求

一、小程序网络请求限制 1、必须https类型的接口 2、必须将接口的域名添加到信任列表中 二、配置request合法域名 配置步骤&#xff1a;登录微信小程序管理后台 -> 开发 -> 开发设置 -> 服务器域名 -> 修改 request 合法域名 点击修改request合法域名&#xf…

【自动化测试】从0开始玩转docker—— 01软件安装

目的 CI / CD在目前各类互联网企业中已然成为推动软件开发行为的重要基础设施服务。同样的对于测试团队来说更是有着举足轻重的重大意义&#xff0c;无论是测试左移的具象化提现亦或是持续测试的顺利开展&#xff0c;掌握这一技能已是广大软件测试工程师的必修课。分享这一技术…

Springboot+Vue+Uniapp自媒体视频系统

简介&#xff1a;本项目采用了基本的springbootvueuniapp设计的自媒体系统。详情请看主要截图。经测试&#xff0c;本项目正常运行。本项目适用于Java毕业设计、课程设计学习参考等用途。 项目描述 项目名称SpringbootVueUniapp自媒体视频系统源码作者LHL项目类型Java EE项目 …