【JavaEE多线程】线程中断 interrupt()

系列文章目录

🌈座右铭🌈:人的一生这么长、你凭什么用短短的几年去衡量自己的一生!

💕个人主页:清灵白羽 漾情天殇_计算机底层原理,深度解析C++,自顶向下看Java-CSDN博客

❤️相关文章❤️:清灵白羽 漾情天殇-CSDN博客


目录

系列文章目录

一、终止一个线程

1、标记位终止线程

        1、定义一个共享的标记变量

        2、在线程的执行任务当中周期性检查标记

        3、提供公共方法来设置标记

        4、代码展示标记位终止线程

2、调用interrupt()方法

      1、interrupt()方法

      2、interrupted()方法

      3、isInterrupted()方法

      4、如何判断应该使用哪种方法呢?

      5、什么情况下需要清除中断状态,又为什么要清除中断状态呢?

拓展:

二、线程等待


一、终止一个线程

1、标记位终止线程

        在Java当中通过共享的标记位来终止线程是一种常见的方式,这种方式通常设计一个布尔类型的变量,通常被称为标记或者标志,用来指示线程是否应该终止,线程在执行任务的时候会周期性地检查这个标记,并且标记指示终止时主动退出执行。

        1、定义一个共享的标记变量

        

private volatile boolean shouldTerminate = false;

        这里使用了volatile这个关键字,后续我会为大家详细介绍这个关键字的用法,大家这里先暂时忽略它。

        2、在线程的执行任务当中周期性检查标记

        在线程的任务当中通过周期性地检查标记来确定是否应该被终止,通常在循环当中检查标记。

     

public void run() {
    while (!shouldTerminate) {
        // 执行任务
    }
}

        当这个标记位为true的时候,线程就会退出循环,从而终止执行任务。

        3、提供公共方法来设置标记

        在需要终止线程的时候,提供一个公共方法来设置标记为true。

public void requestTermination() {
    shouldTerminate = true;
}

        4、代码展示标记位终止线程

public class Main{
    private static class MyRunnable implements Runnable{
        private volatile boolean shouldTerminate = false;

        @Override
        public void run() {
            while (!shouldTerminate){
                System.out.println("Thread is running...");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            System.out.println("Thread terminated...");
        }
        public void requestTermination(){
            shouldTerminate = true;
        }
    }
    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        Thread thread = new Thread(myRunnable);
        thread.start();
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        myRunnable.requestTermination();
    }
}

        在我的示例代码当中,MyRunnable类声明为静态内部类,有以下几个原因:

        1、静态内部类可以直接访问外部类的静态成员

        2、静态内部类的实例化不依赖外部类的实例

        3、静态内部类可以更方便地重用和单独测试:将M有Runnable声明为静态内部类可以使得它更容易被其它类重用,并且可以在不依赖外部类的情况下单独测试。

2、调用interrupt()方法

        我在这里要声明以下只有interrupt方法才能中断线程,其余两个方法只是检查线程当前的线程状态的,这里一定不要混淆。    

      1、interrupt()方法

  • interrupt()方法是Thread类的实例方法,用于向目标线程发送中断信号,即设置目标线程的中断状态为true。
  • 如果目标线程正在阻塞(如调用了sleep()wait()join()等方法),那么会抛出InterruptedException异常。
  • 如果目标线程正在运行,那么只是简单地设置其中断状态为true,线程需要在合适的时机自行检查中断状态并作出响应。

      2、interrupted()方法

        这里的方法其实就是系统为我们自动维护的一个标记位,不需要我们在手动维护了,一会我写代码各位就能够看懂了。

  • interrupted()是Thread类的静态方法,用于检查当前线程的中断状态,并清除中断状态(将中断状态重置为false)。
  • 如果当前线程的中断状态为true,则返回true;否则返回false。
  • interrupted()方法还可以用来检查其他线程的中断状态,即Thread.interrupted()会检查调用它的线程的中断状态。

        3、isInterrupted()方法

  • isInterrupted()是Thread类的实例方法,用于检查目标线程的中断状态,但不会清除中断状态。
  • 如果目标线程的中断状态为true,则返回true;否则返回false。
  • isInterrupted()方法可以用来检查其他线程的中断状态,即通过thread.isInterrupted()来检查指定线程的中断状态。

        总结:

  • interrupt()方法是设置线程中断状态为true的方法,用于向目标线程发送中断信号。
  • interrupted()方法是用于检查当前线程中断状态并清除中断状态。
  • isInterrupted()方法是用于检查目标线程中断状态,但不会清除中断状态。

        4、如何判断应该使用哪种方法呢?

  • 如果你希望向一个线程发送中断信号,让它在合适的时候自行终止执行,那么使用interrupt()方法是比较合适的。这种方式允许线程自行决定如何响应中断信号,可以更安全地终止线程的执行。

  • 如果你需要在一个线程中检查自身的中断状态,并清除中断状态,可以使用interrupted()方法。这种方式适合在执行任务的线程中周期性地检查中断状态,以便及时响应中断信号并执行相应的清理操作。

  • 如果你需要检查其他线程的中断状态,而且不想清除中断状态,可以使用isInterrupted()方法。这种方式适合在一个线程中检查其他线程的中断状态,例如在监控线程池中线程的执行情况时。

        5、什么情况下需要清除中断状态,又为什么要清除中断状态呢?

        清除中断状态通常发生在一些特定的情况下,这些情况通常涉及到线程的异常处理或者线程的复用。

        1、异常处理:在捕获了InterruptedException异常之后,需要清除线程的中断状态。

        2、线程复用:当一个线程执行完某个任务后,可能需要复用该线程来执行其他任务。

        清除中断状态就是将线程判断是否中断的标记位设置为初始值也就是false,清除中断状态就是告诉其它线程这个线程没有被中断。

        在Java中,当线程被中断时,它的中断状态会被设置为true。这个中断状态可以通过调用Thread.interrupted()isInterrupted()方法来检查。

        InterruptedException异常通常是在线程调用了一些可能会抛出InterruptedException的阻塞方法(例如Thread.sleep()、Object.wait()、Thread.join()等)时才会抛出。当线程处于阻塞状态(例如调用了上述方法),而且此时又接收到了中断请求时,这些阻塞方法会抛出InterruptedException异常。这样做的目的是让线程在阻塞状态中响应中断请求,从而提高线程的响应性。因为阻塞的线程无法响应中断请求这个时候抛出异常并且在抛出异常之前系统会自动清除中断状态,让这个目标线程以非中断的状态去响应这个中断。并不是所有的中断请求都会导致InterruptedException异常的抛出。如果线程正在执行非阻塞的任务,而此时接收到中断请求,那么线程就不会抛出InterruptedException异常,而是需要通过检查中断状态来判断是否应该终止执行。

        上述的interrupted()方法是手动清除中断状态,抛出异常这个操作是系统自动清除中断状态,不管怎样目的都是为了清除中断状态让线程继续执行剩余的业务逻辑。

public class Main {
    public static void main(String[] args) {
        Thread thread = new Thread(new MyRunnable());
        thread.start();
        try {
            Thread.sleep(2000);
            thread.interrupt();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    static class MyRunnable implements Runnable{
        @Override
        public void run() {
            System.out.println("子线程开始执行...");
            try {
                Thread.sleep(5000);
                System.out.println("子线程睡眠结束...");
            } catch (InterruptedException e) {
                System.out.println("子线程被中断...");
                e.printStackTrace();
            }
            if (Thread.currentThread().isInterrupted()){
                System.out.println("未被清除!");
            }else {
                System.out.println("已被清除");
            }
        }
    }
}

拓展:

        

public class Main {
    private static class MyRunnable implements Runnable{
        @Override
        public void run() {
            while (!Thread.currentThread().isInterrupted()){
                System.out.println("线程运行中");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    System.out.println("中断线程");
                }
            }
            System.out.println("线程已经中断");
        }
    }
    public static void main(String[] args) {
        Thread thread = new Thread(new MyRunnable());
        thread.start();
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        thread.interrupt();
    }
}

        这段代码大家可以试着运行一下,调用interrupt()无法终止线程,当控制台输出中断线程之后,线程会继续执行,这是为什么呢?因为线程在休眠状态下sleep()的时候,系统为了让这个线程响应中断请求,会将他唤醒,并且在抛出异常之前自动清除这个线程的中断状态,也就是这个时候线程的标记位仍然为false,所以这个时候我们必须对这个线程的中断状态进行恢复或者直接使用break关键字终止线程,这里还是推荐大家使用恢复线程中断状态比较好,修改以后的代码如下:

Thread.currentThread().interrupt();

        只需要添加这一行代码即可:

public class Main {
    private static class MyRunnable implements Runnable{
        @Override
        public void run() {
            while (!Thread.currentThread().isInterrupted()){
                System.out.println("线程运行中");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    System.out.println("中断线程");
                    Thread.currentThread().interrupt();
                    e.printStackTrace();
                }
            }
            System.out.println("线程已经中断");
        }
    }
    public static void main(String[] args) {
        Thread thread = new Thread(new MyRunnable());
        thread.start();
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        thread.interrupt();
    }
}

        我们使用这行代码将线程的中断状态恢复,线程就可以顺利中断了。


二、线程等待

         

        join()方法是 Thread 类提供的一个方法,用于让一个线程等待另一个线程的结束。具体来说,当一个线程调用另一个线程的 join() 方法时,它会阻塞自己的执行,直到被等待的线程执行结束才继续执行。

这个方法提供了一种线程之间的协作机制,允许一个线程等待另一个线程完成某些重要的工作,然后再继续执行。它通常用于主线程等待子线程的完成,或者一个线程等待其他一组线程的完成。

join() 方法有多个重载形式:

  1. join():使当前线程等待被调用对象的执行完成。
  2. join(long millis):使当前线程等待被调用对象的执行完成,但最多等待指定的毫秒数。
  3. join(long millis, int nanos):使当前线程等待被调用对象的执行完成,但最多等待指定的毫秒数和纳秒数。

使用 join() 方法的一个常见模式是创建一个线程并启动它,然后在主线程中调用该线程的 join() 方法,以等待该线程的完成。例如:

public class Main {
    public static void main(String[] args) {
        Thread thread = new Thread(new MyRunnable());
        thread.start(); // 启动子线程

        try {
            thread.join(); // 主线程等待子线程执行完成
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("子线程执行完成,主线程继续执行...");
    }

    static class MyRunnable implements Runnable {
        @Override
        public void run() {
            System.out.println("子线程开始执行...");
            // 模拟子线程执行一些耗时操作
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("子线程执行完成。");
        }
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

动态酷黑主页源码

效果图 PC端 &#xff08;移动端不能访问&#xff09; 部分代码 index.html <!DOCTYPE html> <html lang"zh-CN"> <head> <meta http-equiv"X-UA-Compatible" content"IEedge,chrome1"> <meta charset"ut…

java算法day58 | 单调栈part01 ● 739. 每日温度 ● 496.下一个更大元素 I

739. 每日温度 思路&#xff1a; 这道题用暴力求解法会超时。 那我们就要想如何只遍历一遍就能求解出每个位置的下一个更大值在哪呢。 主要的思想就是空间换时间。定义一个单调栈&#xff0c;每次遇到比栈顶元素小的或相等的&#xff0c;直接入栈&#xff0c;遇到比栈顶元素大的…

电学启蒙积木电子方案

东莞市酷得智能科技有限公司是一家集芯片贸易和电子方案定制开发的研发型公司&#xff0c;其中电子积木方案是酷得经营多年的其中一条比较成熟的研发线。电学积木玩具不仅仅是一种娱乐工具&#xff0c;更是一种教育工具&#xff0c;能够在孩子们的成长过程中发挥多方面的积极作…

微信小程序开发五(与springboot整合)

首先在微信开发者工具中开启不校验合法域名&#xff0c;这个才能本地访问 实现一个小功能&#xff1a; 展示数据信息&#xff0c;每条数据的颜色不一样 后端&#xff1a;springbootmybatisplusmysql 依赖&#xff1a; <dependency><groupId>com.baomidou</grou…

代码学习记录45---单调栈

随想录日记part45 t i m e &#xff1a; time&#xff1a; time&#xff1a; 2024.04.17 主要内容&#xff1a;今天开始要学习单调栈的相关知识了&#xff0c;今天的内容主要涉及&#xff1a;每日温度 &#xff1b;下一个更大元素 I 739. 每日温度 496.下一个更大元素 I Topic…

powershell@命令行提示符样式配置自定义@pwsh重写prompt显示电量内存时间等信息

文章目录 abstract流行的powershell prompt模块示例 powershell原生修改Prompt函数配置文档Prompt命令来自哪里 简单修改带上电量和时间的Prompt 复杂修改预览FAQ:没有必要修改相关仓库地址样式选择平衡样式花哨样式响应性能 小结 abstract 在 PowerShell 中&#xff0c;可以通…

国家级项目管理高级认证:CSPM-4级(高级)重磅推出

本周&#xff0c;圣略CSPM资深讲师老杨&#xff0c;赴北京参加CSPM-4级高级讲师培训&#xff0c;从现场带来第1手的资料&#xff0c;与大家分享&#xff1a; CSPM-4基本要求&#xff1a; 负责实现组织战略目标&#xff0c;以成果和收益为导向&#xff0c;需具备战略解析、收益…

汇编语言学习笔记

1、NOP指令&#xff1a;号称最安全的指令&#xff0c;全名为no Operation&#xff0c;一条nop指令占用一个字节&#xff0c;什么也不做。有时编译器会使用该指令将代码对齐到偶数地址边界&#xff08;类似于内存对齐&#xff09;。IA-32处理器从偶数双字地址处加载代码和数据时…

【简单介绍下Beego框架】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

等保合规:保护企业网络安全的必要性与优势

前言 无论是多部网络安全法律法规的出台&#xff0c;还是最近的“滴滴被安全审查”事件&#xff0c;我们听得最多的一个词&#xff0c;就是“等保。” 只要你接触安全类工作&#xff0c;听得最多的一个词&#xff0c;一定是“等保。” 那么&#xff0c;到底什么是“等保”呢…

c++初阶——类和对象(上)

大家好我是小锋今天我们来学习类和对象 面向过程和面向对象初步认识 C语言是面向过程的&#xff0c;关注的是过程&#xff0c;分析出求解问题的步骤&#xff0c;通过函数调用逐步解决问题。 C是基于面向对象的&#xff0c;关注的是对象&#xff0c;将一件事情拆分成不同的对…

NASM中的-f选项

2024年4月19日&#xff0c;周五下午 -f选项 在 NASM 中&#xff0c;-f 选项用于指定输出格式或目标文件格式。这个选项允许你告诉 NASM 将汇编代码编译成特定格式的目标文件&#xff0c;以便与特定的操作系统或环境兼容。下面是 -f 选项的一些常见用法和参数&#xff1a; -f …

✌粤嵌—2024/4/11—合并区间✌

代码实现&#xff1a; /*** Return an array of arrays of size *returnSize.* The sizes of the arrays are returned as *returnColumnSizes array.* Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().*/// 交换 void swap(i…

“开关是灯的日出日落,日出日落是灯的开关”

C语言刷题 day01 本篇是C语言刷题大杂烩&#xff0c;收集了笔者遇到的认为有价值的题目&#xff0c;本篇会持续更新~~ day01 至少是其他数字两倍的最大数 题目原文&#xff1a; 题意解析&#xff1a; 请你找出数组中的最大元素并检查它是否 至少是数组中每个其他数字的两倍 …

【汇智知了堂来袭】西华师范大学鸿蒙专题讲座,共探HarmonyOS新机遇!

在这个信息化的时代&#xff0c;我们身处一个日新月异、科技飞速发展的世界。随着信创国产化的步伐加快&#xff0c;万物互联的大时代已经悄然开启。作为科技前沿的探索者&#xff0c;汇智知了堂始终站在行业的前沿&#xff0c;紧跟时代的发展脉搏。我们在4月9日走进西华师范大…

5. Django 探究CBV视图

5. 探究CBV视图 Web开发是一项无聊而且单调的工作, 特别是在视图功能编写方面更为显著. 为了减少这种痛苦, Django植入了视图类这一功能, 该功能封装了视图开发常用的代码, 无须编写大量代码即可快速完成数据视图的开发, 这种以类的形式实现响应与请求处理称为CBV(Class Base…

第一届AI Agent智能体现场开发大赛报名开启!8月上旬火热开赛~

由联想拯救者、AIGC开放社区、英特尔携手主办的“AI生成未来第二届拯救者杯OPENAIGC开发者大赛”已经正式启动&#xff0c;“2024 AI Agent极限挑战赛”作为特设专项赛道&#xff0c;也将同步于8月上旬开赛&#xff0c;参赛者将在更加紧张刺激的现场比赛中展现其技术与创造力。…

TypeScript 基础:接口、泛型和自定义类型在 Vue 3 中的应用

接口&#xff08;Interfaces&#xff09; 首先&#xff0c;我们定义一个接口 PersonInter 来描述一个人的信息&#xff0c;包括 id、name 和 age。 interface PersonInter {id: string;name: string;age: number; }自定义类型&#xff08;Custom Types&#xff09; 然后&…

如何在Windows 10中启用和使用上帝模式,这里有详细步骤

序言 上帝模式&#xff08;God Mode&#xff09;是一个特殊的文件夹&#xff0c;只在一个窗口中显示所有可用的操作设置。它可以节省搜索命令的时间&#xff0c;而无需知道通过“开始”菜单或“控制面板”查找命令的步骤。上帝模式默认情况下是隐藏的&#xff0c;所以我们需要…

世界500强:破解“智慧核能”数智化成功转型密码

近日&#xff0c;实在智能携手中国核能行业协会信息化专业委员会在中国人工智能小镇成功举办“基于大模型的RPA数字员工在核能行业实战应用案例专项培训”&#xff0c;中国核工业集团、中国广核集团、国家电力投资集团等企事业单位共同参加。中核集团作为我国核科技工业的主体&…
最新文章