如何优雅的终止线程 Java

news2025/7/19 12:46:07

目录

终止线程的方法

打断sleep函数

打断正常执行的线程

两阶段终止模式

错误的方法

使用线程对象的 stop() 方法停止线程

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

正确的方法:使用 interrrupt


终止线程的方法

XXXThread.interrupt();

在线程的 run函数中对该线程的中断标记进行判断,自行决定是否终止当前线程。

以及在终止线程之前做一些工作。

interrupt 这个方法并没有强制性地去中断线程任务,只是发送了一个信号给到线程自身,然后让线程自身去决定如何执行。

正因为 interrupt 的灵活性会比较高,所以在 JDK 的线程池中,关于关闭部分的实现也是采用了 interrupt 去实现。

打断sleep函数


public class InterruptThread2 {

    static class TestInterruptedStop implements Runnable {
        @Override
        public void run() {
            synchronized (this) {
                //如果当前线程被中断,这里需要主动退出
                for (int i = 0; i < 100; i++) {
                    try {
                        Thread.sleep(1000);// sleep 被打断 抛出异常InterruptedException
                        // 之后打断标记被清空
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        System.out.println("sleep遇到了中断,程序即将终止");
                        System.out.println("终止前的相关操作...");
                    }
                    System.out.println("running " + (i+1));
                }
                System.out.println("end");
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {

        Thread testInterruptedStop = new Thread(new TestInterruptedStop());
        testInterruptedStop.start();

        Thread.sleep(2000);
        testInterruptedStop.interrupt();
        Thread.sleep(1000);
        System.out.println("testInterruptedStop is interrupted:" + testInterruptedStop.isInterrupted());

    }

}

打断正常执行的线程


public class InterruptThread3 {

    static class TestInterruptedStop implements Runnable {
        @Override
        public void run() {
            synchronized (this) {
                int i = 1;
                while(!Thread.currentThread().isInterrupted()){
                    System.out.println("running " + (i++));
                }
                if(Thread.currentThread().isInterrupted()){// 如果当前线程是打断状态
                    System.out.println("遇到了中断,程序即将终止");
                    System.out.println("执行终止前的相关操作...");
                }
                System.out.println("end");
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Thread testInterruptedStop = new Thread(new TestInterruptedStop());
        testInterruptedStop.start();

        Thread.sleep(2000);
        testInterruptedStop.interrupt();
        Thread.sleep(1000);
        System.out.println("testInterruptedStop is interrupted:" + testInterruptedStop.isInterrupted());

    }

}

两阶段终止模式

在一个线程 T1 中如何 优雅 终止线程 T2 ?这里的【优雅】指的是给 T2 一个料理后事的机会。

错误的方法

使用线程对象的 stop() 方法停止线程


stop 方法会真正杀死线程,如果这时线程锁住了共享资源,那么当它被杀死后就再也没有机会释放锁,其它线程将永远无法获取锁


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


目的仅是停止一个线程,但这种做法会让整个程序都停止

正确的方法:使用 interrrupt

如果被打断线程正处于 sleepwaitjoin这三种状态,则会导致被打断的线程抛出 InterruptedException,并清除打断标记,也就是置为 false。

@Slf4j(topic = "c.TestTwoPhaseTermination")
public class TestTwoPhaseTermination {
    public static void main(String[] args) throws InterruptedException {
        TPTInterrupt t = new TPTInterrupt();
        t.start();

        Thread.sleep(3500);
        log.debug("stop");
        t.stop();
    }
}
@Slf4j(topic = "c.TPTInterrupt")
class TPTInterrupt {
    private Thread thread;

    public void start(){
        thread = new Thread(() -> {
            while(true) {
                Thread current = Thread.currentThread();
                if(current.isInterrupted()) {
                    log.debug("料理后事");
                    break;
                }
                try {
                    Thread.sleep(1000);
                    log.debug("将结果保存");
                } catch (InterruptedException e) {
                    current.interrupt();// 打断标记被清空,需要重新打断设置打断标记为 true
                }

            }
        },"监控线程");
        thread.start();
    }

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

sleep 的睡眠被打断会抛出异常,情况打断标记,因此在 catch 块中,需要重新设置打断标记。

 

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

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

相关文章

NFT+体育,卡塔尔世界杯有哪些NFT看点!

有人说没有冷门的世界杯不是真正的世界杯&#xff01;11月22日&#xff0c;卡塔尔世界杯小组赛C组第1轮比赛中&#xff0c;沙特爆冷2:1逆转阿根廷队&#xff0c;成了今年世界杯的第一个冷门。世界排名第51位的沙特队战胜了排名第3的阿根廷队&#xff0c;结束了阿根廷队此前的36…

vue拖拽删除实现

拖拽删除 背景 自营上传图片&#xff0c;但是需要排序和删除功能&#xff0c;所以用到了h5的拖拽 源元素&#xff1a; 即被拖拽的元素。 目标元素&#xff1a; 即合法的可释放元素。 每个事件的事件主体都是两者之一。 拖拽事件 触发顺序及次数 被拖拽元素&#xff0c;事…

day5-day6【代码随想录】螺旋矩阵II

文章目录前言一、螺旋矩阵||&#xff08;力扣59&#xff09;二、螺旋矩阵&#xff08;力扣54&#xff09;前言 坚持循环不变量原则。 模拟顺时针画矩阵的过程: 填充上行从左到右 填充右列从上到下 填充下行从右到左 填充左列从下到上 由外向内一圈一圈这么画下去 一、螺旋矩阵…

大三保研夏令营须知及前期准备工作

前言 对于大三保研学生而言&#xff0c;学期将近结束&#xff1b;接踵而来的是接下来的保研准备。保研阶段通常可以分为&#xff1a;夏令营、预推免、九推(捡漏)。很多同学往往都是在前两个阶段就能获得满意的offer。 对于计算机专业来说&#xff0c;经历过2022年的“推免季”&…

项目实战——匹配系统(下)

目录 一、整体梳理 二、创建SpringCloud目录 三、创建子项目 四、实现接口 五、config网关配置 六、放行API 七、封装后端逻辑 八、对接匹配系统 九、修改数据库 十、实现匹配之后的逻辑 十一、线程锁 十二、匹配函数 上节课知识梳理&#xff1a; 用户浏览器打开之…

天津专升本报名时的报名点

2023年天津专升本报名区县及应届生、往届生报名点 天津市在校大三应届生报名点选自己的专科院校&#xff0c;往届生及在外省就读的应届生选户籍所在区招办。 退役士兵从天津入伍的选择学校作为报名点&#xff0c;外省市入伍的选择区招办。

slambook2(ch2)—— Ubuntu20.04 使用cmake + make自动化编译过程

slambook2&#xff08;ch2&#xff09;—— Ubuntu20.04 使用cmake make自动化编译过程主函数库函数libhello.cpplibhello.hCMakeLists.txt编译重新编译vim加行号主函数 main.cpp 库函数 libhello.cpp libhello.h CMakeLists.txt 编译 mkdir build && cd build c…

ASEMI肖特基二极管MBR30100CT特征,MBR30100CT应用

编辑-Z ASEMI肖特基二极管MBR30100CT参数&#xff1a; 型号&#xff1a;MBR30100CT 最大重复峰值反向电压&#xff08;VRRM&#xff09;&#xff1a;100V 最大平均正向整流输出电流&#xff08;IF&#xff09;&#xff1a;30A 峰值正向浪涌电流&#xff08;IFSM&#xff0…

通达信l1l2行情接口-十档行情有哪些优势?

据提供系统或用户编制的条件选股公式进行选股选定一个条件选股公式或多个组合条件后&#xff0c;计算机自动帮您选出当时或历史上某一段时间内满足条件的所有股票十档行情 英文&#xff0c;列在行情下载显示窗口&#xff0c;同时可保留成板块。 那通达信l1l2行情接口-十档行情…

map容器(20221125)

一、map/multimap容器 1、map基本概念 map中所有元素都是pair&#xff1b; pair第一个元素为key&#xff08;键值&#xff09;,起到索引的作用&#xff0c;第二个元素为value(实值)&#xff1b; 所有元素会根据元素的键值&#xff08;key&#xff09;自动排序。 map/multi…

论文阅读笔记 | 三维目标检测——PartA2算法

如有错误&#xff0c;恳请指出。 文章目录0. 前言与补充知识1. 背景2. 相关工作3. 网络结构3.1 Part-aware stageAnchor-free Proposal GenerationAnchor-based Proposal GenerationDiscussion Two Proposal Generation Strategies3.2 Part-aggregation stageROI-aware feature…

ORB-SLAM2 ---- Frame::ComputeBoW函数(TrackReferenceKeyFrame调用版)

目录 1.函数作用 2.什么是BowVec和FeatVec 3.代码 3.1 Frame::ComputeBoW解释 3.2 transform主函数&#xff1a;将一幅图像所有的特征点转化为BowVector和FeatureVector 3.3 transform&#xff1a;将描述子转化为Word id&#xff0c; Word weight&#xff0c;节点所属的…

[毕业设计]机器学习水域检测标注算法

前言 &#x1f4c5;大四是整个大学期间最忙碌的时光,一边要忙着备考或实习为毕业后面临的就业升学做准备,一边要为毕业设计耗费大量精力。近几年各个学校要求的毕设项目越来越难,有不少课题是研究生级别难度的,对本科同学来说是充满挑战。为帮助大家顺利通过和节省时间与精力投…

uniapp里接入lottie-miniprogram详细指南

包工头&#xff1a;小张啊&#xff0c;我们页面里那几个gif也太low了&#xff0c;你能不能追求远大点。ui妹子&#xff1a;软件推荐可以用lottie实现。我&#xff1a;这玩意我耍过&#xff0c;交给我了。 牛逼已经吹出去了&#xff0c;开干&#xff0c; 遇到问题有&#xff0…

基于MxNet实现目标检测-YoloV3【附部分源码及模型】

文章目录前言目标检测发展史及意义一、数据集的准备1.标注工具的安装2.数据集的准备3.标注数据4.解释xml文件的内容二、网络结构的介绍三、代码实现0.工程目录结构如下1.导入库2.配置GPU/CPU环境3.数据加载器4.模型构建YoloV3-tinyYoloV35.模型训练1.学习率设置2.优化器设置3.损…

XSS绕过安全狗WAF

今天继续给大家介绍渗透测试相关知识&#xff0c;本文主要内容是XSS绕过安全狗WAF。 一、测试环境搭建 我们使用Vmware虚拟机搭建靶场环境。在Vmware虚拟机上&#xff0c;安装有PHPStudy&#xff0c;如下所示&#xff1a; 然后安装安全狗WAF&#xff0c;安全狗WAF有一系列的…

深度学习入门(五十二)计算机视觉——风格迁移

深度学习入门&#xff08;五十二&#xff09;计算机视觉——风格迁移前言计算机视觉——风格迁移课件样式迁移易于CNN的样式迁移教材1 方法2 阅读内容和风格图像3 预处理和后处理4 抽取图像特征5 定义损失函数5.1 内容损失5.2 风格损失5.3 全变分损失5.4 损失函数6 初始化合成图…

【瑞萨RA4M2】开发环境搭建和点灯指南

【瑞萨RA4系列开发板体验】开发环境搭建和新手点灯指南 文章目录【瑞萨RA4系列开发板体验】开发环境搭建和新手点灯指南一、简单开箱二、芯片简介三、开发环境搭建2.1 安装FSP(RASC)2.2 安装Keil MDK2.3 安装RA4M2 Keil Pack2.4 安装RFP(瑞萨烧录工具)三、新手点灯指南3.1 创建…

hoops编程指南:04.4用户交互突出显示

user interaction highlighting 1.突出显示 在执行选择之后&#xff0c;通常需要向用户提供关于所选内容的视觉反馈。例如&#xff0c;场景可能包含由多个几何体表示的飞机机翼的图片。然而&#xff0c;HOOPS Visualize对飞机机翼这一独特概念一无所知。因此&#xff0c;如果…

ES6 入门教程 28 异步遍历器 28.1 同步遍历器的问题 28.2 异步遍历的接口 28.3 for await...of

ES6 入门教程 ECMAScript 6 入门 作者&#xff1a;阮一峰 本文仅用于学习记录&#xff0c;不存在任何商业用途&#xff0c;如侵删 文章目录ES6 入门教程28 异步遍历器28.1 同步遍历器的问题28.2 异步遍历的接口28.3 for await...of28 异步遍历器 28.1 同步遍历器的问题 Itera…