Java:关于Java中的线程中断的几种方法

2023-10-31

Java:关于Java中的线程中断的几种方法

1.使用线程的stop()来中断线程
2.使用线程的interrupt()来中断线程
3.通过共享变量来控制

使用线程的stop()来中断线程

这种方式是直接调用线程的stop()方法,可以直接让线程终止运行,是一种很暴力的方式。

    public static void test02(){
        Thread thread1 = new Thread(()->{
            System.out.println("thread1启动了");
            while (true){
                System.out.println("thread1循环中...");
            }
        });
        thread1.start();
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("准备关闭thread1线程");
        thread1.stop();

        System.out.println("主线程停止");
    }

运行结果如下
在这里插入图片描述

使用线程的interrupt()来中断线程

    public static void testInterrupt(){
        Thread thread1 = new Thread(() -> {
            while (true){
                boolean interrupted = Thread.currentThread().isInterrupted();
                if(interrupted){
                    System.out.println("thread1线程被中断");
                    break;
                }
                System.out.println("thread1循环中...");
            }
        });

        thread1.start();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        thread1.interrupt();
    }

运行结果如下
在这里插入图片描述
interrupt相比于stop中断线程的方式更加温柔,当主线程调用thread1线程的interrupt方法其实本质就是将thread1线程的中断标志设置为true,仅此而已。被设置中断标志的线程还是可以继续运行的,不受影响,也就是如果thread不主动结束线程该线程是不会停止的。
代码演示如下

    public static void testInterrupt2(){
        Thread thread1 = new Thread(() -> {

            while (true){
                boolean interrupted = Thread.currentThread().isInterrupted();
                System.out.println("当前中断标志位状态为:"+interrupted);
                System.out.println("thread1循环中...");
            }
        });

        thread1.start();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        thread1.interrupt();
    }

运行结果如下
在这里插入图片描述
当调用了thread1.interrupt();之后thread1还会一直无限执行下去。

如果thread1线程处于被阻塞状态(例如处于sleep,wait,join等状态),在别的线程调用thread1的interrupt方法,那么线程的中断状态会被清除,并抛出InterruptedException异常

代码如下

    public static void testInterrupt3(){
        Thread thread1 = new Thread(() -> {
            System.out.println("thread1线程启动了。。。");
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        });

        thread1.start();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        thread1.interrupt();
    }

运行结果如下
在这里插入图片描述
1.线程启动是,默认中断标志位为false
2.如果main线程调用了thread1的interrupt()方法,中断标志位就变成了true
3.正常情况,中断标志位为true,如果thread1判断中断标志位为true就中断执行,则thread1停止,如果thread1线程自己不终止运行则不会停止。
4.异常情况,如果thread1线程正处于阻塞状态(例如处于sleep,wait,join等状态),将会把中断状态清除,并且将抛出InterruptedException异常,此时中断标志位还是false,thread1线程还会继续执行。
测试异常情况,并且循环不停止的情况,代码如下

    public static void testInterrupt4(){
        Thread thread1 = new Thread(() -> {
            System.out.println("thread1线程启动了。。。");
            try {
                Thread.sleep(5000);
            } catch (Exception e) {
                e.printStackTrace();
            }
            while (true){
                boolean interrupted = Thread.currentThread().isInterrupted();
                if(interrupted){
                    System.out.println("thread1程序终止");
                    break;
                }
            }
        });

        thread1.start();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        thread1.interrupt();
    }

在这里插入图片描述
程序并没有停止

5.解决异常情况的方法,就是在catch块中,需要再次将中断标志位设置为true,2次调用才能使中断标志位改为true

    public static void testInterrupt5(){
        Thread thread1 = new Thread(() -> {
            System.out.println("thread1线程启动了。。。");
            try {
                Thread.sleep(5000);
            } catch (Exception e) {
	            // 抛出异常过后在此调用interrupt方法
                Thread.currentThread().interrupt();
                e.printStackTrace();
            }
            while (true){
                boolean interrupted = Thread.currentThread().isInterrupted();
                if(interrupted){
                    System.out.println("thread1程序终止");
                    break;
                }
            }
        });

        thread1.start();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        thread1.interrupt();
    }

在这里插入图片描述

关于Thread.interrupted()方法

判断线程是否被中断并清除当前中断状态
这个方法做了两件事情
1.返回当前线程的中断状态
2.将当前线程的中断状态清零并重新设置为false,清除线程的中断状态

    public static void testInterrupt6(){
        System.out.println(Thread.currentThread().getName() + "\t" + Thread.interrupted());
        System.out.println(Thread.currentThread().getName() + "\t" + Thread.interrupted());
        System.out.println("1111111111111111");

        // 中断标志位设置为true
        Thread.currentThread().interrupt();

        System.out.println("2222222222222222");
        System.out.println(Thread.currentThread().getName() + "\t" + Thread.interrupted());
        System.out.println(Thread.currentThread().getName() + "\t" + Thread.interrupted());

    }

在这里插入图片描述

关于isInterrupted()方法

该方法只会返回当前线程的中断标志位的状态;不会清除当前线程的中断标志位的状态

    public static void testInterrupt7(){
        System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().isInterrupted());
        System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().isInterrupted());
        System.out.println("1111111111111111");

        // 中断标志位设置为true
        Thread.currentThread().interrupt();

        System.out.println("2222222222222222");

        System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().isInterrupted());
        System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().isInterrupted());
    }

在这里插入图片描述

关于Thread的静态方法interrupted和Thread实例方法isInterrupted底层源码

1.interrupted

    public static boolean interrupted() {
        return currentThread().isInterrupted(true);
    }

2.isInterrupted

    public boolean isInterrupted() {
        return isInterrupted(false);
    }

本质上都是调用了实例的isInterrupted方法,只是传入的参数有所不同,当传入true时,会情空当前线程的中断标志,重置为false,方传入false时,不会清空。

private native boolean isInterrupted(boolean ClearInterrupted);

该方法是被native修饰的方法

总结

  1. public void interrupt() 其中interrupt()是一个实例方法
    它通知目标线程中断,也仅仅是设置目标线程的中断标志位为true.
  2. public boolean isInterrupted() 其中isInterrupted()方法也是一个实例方法
    它判断当前线程是否被中断(通过检查中断标志位)并获得中断标志
  3. public static boolean interrupted() . 该方法是Thread类的静态方法
    返回当前线程的中断状态真实值后会将当前线程的中断状态设置为false,此方法调用之后会清除当前线程的中断标志位的状态。

通过共享变量来控制

1.使用volatile 关键字来实现线程中断

    static volatile boolean run = true;
    public static void main(String[] args) {
        new Thread(()->{
            while (run){
                System.out.println("线程1执行中...");
            }
        }).start();

        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        run = false;
        System.out.println("主线程结束");
    }

2.使用同步代码块synchronized来实现线程中断

    static boolean run = true;
    static Object object = new Object();
    public static void main(String[] args) {
        new Thread(()->{
            while (run){
                System.out.println("线程1执行中...");
                synchronized (object){

                }
            }
        }).start();

        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        run = false;
        System.out.println("主线程结束");
    }

3.使用AtomicBoolean 来实现线程中断

    public static void main(String[] args) {

        AtomicBoolean run = new AtomicBoolean(true);
        new Thread(()->{
            while (run.get()){
                System.out.println("线程1执行中...");
            }
        }).start();

        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        run.set(false);
        System.out.println("主线程结束");
    }

其运行结果如下在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java:关于Java中的线程中断的几种方法 的相关文章

  • 如何让 BlazeDS 忽略属性?

    我有一个 java 类 它有一个带有 getter 和 setter 的字段 以及第二对 getter 和 setter 它们以另一种方式访问 该字段 public class NullAbleId private static final
  • 日期语句之间的 JPQL SELECT [关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 我想将此 SQL 语句转换为等效的 JPQL SELECT FROM events WHERE events date BETWE
  • 不同帐户上的 Spring Boot、JmsListener 和 SQS 队列

    我正在尝试开发一个 Spring Boot 1 5 应用程序 该应用程序需要侦听来自两个不同 AWS 帐户的 SQS 队列 是否可以使用 JmsListener 注解创建监听器 我已检查权限是否正确 我可以使用 getQueueUrl 获取
  • 在内存中使用 byte[] 创建 zip 文件。 Zip 文件总是损坏

    我创建的 zip 文件有问题 我正在使用 Java 7 我尝试从字节数组创建一个 zip 文件 其中包含两个或多个 Excel 文件 应用程序始终完成 没有任何异常 所以 我以为一切都好 当我尝试打开 zip 文件后 Windows 7 出
  • 为什么 JTables 使 TableModel 在呈现时不可序列化?

    所以最近我正在开发一个工具 供我们配置某些应用程序 它不需要是什么真正令人敬畏的东西 只是一个具有一些 SQL 脚本生成功能并创建几个 XML 文件的基本工具 在此期间 我使用自己的 AbstractTableModel 实现创建了一系列
  • Pig Udf 显示结果

    我是 Pig 的新手 我用 Java 编写了一个 udf 并且包含了一个 System out println 其中的声明 我必须知道在 Pig 中运行时该语句在哪里打印 假设你的UDF 扩展了 EvalFunc 您可以使用从返回的 Log
  • jQuery AJAX 调用 Java 方法

    使用 jQuery AJAX 我们可以调用特定的 JAVA 方法 例如从 Action 类 该 Java 方法返回的数据将用于填充一些 HTML 代码 请告诉我是否可以使用 jQuery 轻松完成此操作 就像在 DWR 中一样 此外 对于
  • Java 公历日历更改时区

    我正在尝试设置 HOUR OF DAY 字段并更改 GregorianCalendar 日期对象的时区 GregorianCalendar date new GregorianCalendar TimeZone getTimeZone GM
  • 没有 Spring 的自定义 Prometheus 指标

    我需要为 Web 应用程序提供自定义指标 问题是我不能使用 Spring 但我必须使用 jax rs 端点 要求非常简单 想象一下 您有一个包含键值对的映射 其中键是指标名称 值是一个简单的整数 它是一个计数器 代码会是这样的 public
  • 检测并缩短字符串中的所有网址

    假设我有一条字符串消息 您应该将 file zip 上传到http google com extremelylonglink zip http google com extremelylonglink zip not https stack
  • 在 junit 测试中获取 javax.lang.model.element.Element 类

    我想测试我的实用程序类 ElementUtils 但我不知道如何将类作为元素获取 在 AnnotationProcessors 中 我使用以下代码获取元素 Set
  • jdbc mysql loginTimeout 不起作用

    有人可以解释一下为什么下面的程序在 3 秒后超时 因为我将其设置为在 3 秒后超时 12秒 我特意关闭了mysql服务器来测试mysql服务器无法访问的这种场景 import java sql Connection import java
  • 内部类的构造函数引用在运行时失败并出现VerifyError

    我正在使用 lambda 为内部类构造函数创建供应商ctx gt new SpectatorSwitcher ctx IntelliJ建议我将其更改为SpectatorSwitcher new反而 SpectatorSwitcher 是我正
  • Java ResultSet 如何检查是否有结果

    结果集 http java sun com j2se 1 4 2 docs api java sql ResultSet html没有 hasNext 方法 我想检查 resultSet 是否有任何值 这是正确的方法吗 if resultS
  • 如何访问JAR文件中的Maven资源? [复制]

    这个问题在这里已经有答案了 我有一个使用 Maven 构建的 Java 应用程序 我有一个资源文件夹com pkg resources 我需要从中访问文件 例如directory txt 我一直在查看各种教程和其他答案 但似乎没有一个对我有
  • Eclipse 选项卡宽度不变

    我浏览了一些与此相关的帖子 但它们似乎并不能帮助我解决我的问题 我有一个项目 其中 java 文件以 2 个空格的宽度缩进 我想将所有内容更改为 4 空格宽度 我尝试了 正确的缩进 选项 但当我将几行修改为 4 空格缩进时 它只是将所有内容
  • 不接受任何内容也不返回任何内容的函数接口[重复]

    这个问题在这里已经有答案了 JDK中是否有一个标准的函数式接口 不接受也不返回任何内容 我找不到一个 像下面这样 FunctionalInterface interface Action void execute 可运行怎么样 Functi
  • Android:无法使用 DbHelper 和 Contract 类将数据插入 SQLite

    public class Main2Activity extends AppCompatActivity private EditText editText1 editText2 editText3 editText4 private Bu
  • 找不到符号 NOTIFICATION_SERVICE?

    package com test app import android app Notification import android app NotificationManager import android app PendingIn
  • 包 javax.el 不存在

    我正在使用 jre6 eclipse 并导入 javax el 错误 包 javax el 不存在 javac 导入 javax el 过来 这不应该是java的一部分吗 谁能告诉我为什么会这样 谢谢 米 EL 统一表达语言 是 Java

随机推荐

  • 基于 Opencv python实现批量图片去黑边—裁剪—压缩软件

    简介 批量处理图片文件 批量提取GIF图片中的每一帧 具有范围裁剪 自动去除黑 白边 调整大小 压缩体积等功能 先看一些软件的界面 是基于Tkinter写的GUI 裁剪等功能基于Opencv 下载 我添加了处理GIF的github 原作者的
  • codeStriker(及与svn、bugzilla集成)使用过程记录 续

    下面是codeStriker与svn bugzilla集成使用的脚本 放在codestriker安装目录的bin下 usr bin perl w Create codestriker topic based on subversion co
  • linux后台开发必知的io优化知识总结

    尊重原创版权 https www hanzhangsy com hot 105435 html 更多内容参考 https www hanzhangsy com linux后台开发必知的io优化知识总结 系统学习 IO性能对于一个系统的影响是
  • lua堆栈

    首先了解下c 与lua之间的通信 假设在一个lua文件中有如下定义 hello lua 文件 myName beauty girl 请注意红色数字 代表通信顺序 1 C 想获取Lua的myName字符串的值 所以它把myName放到Lua堆
  • 计算机算法常用术语中英对照(分为两部分 其中一部分表格形式 )

    第一部分 Data Structures 基本数据结构 Dictionaries 字典 Priority Queues 堆 Graph Data Structures 图 Set Data Structures 集合 Kd Trees 线段
  • Python实现子线程代码“同时”执行完毕后,再执行后续函数模块

    在python中用多线程完成任务时 在后面添加了一个提醒函数 结果发现线程开启后提醒函数就触发了 解决方法 将多线程join 起来 就会跑完所有多线程任务再执行后续的函数模块 join 的使用方法 import threading impo
  • pgsql:获取分组中最大或最小的一条数据

    步骤1 查询并排序各分组的记录 sql的查询语句如下 SELECT tb curr read tb arch id ROW NUMBER OVER PARTITION by arch id ORDER BY year month desc
  • AWS实例3T磁盘初始化分区及docker环境部署

    文章目录 一 背景说明 二 磁盘分区 2 1 安装分区工具 2 2 查看是否存在数据盘 2 3 使用Parted工具为数据盘进行分区 2 4 系统重读分区表 2 5 为 dev vdb1分区创建文件系统 2 6 挂载磁盘 三 安装docke
  • Qt进行CSV文件操作

    Qt操作csv文件 csv文件简述 逗号分隔值 Comma Separated Values CSV 有时也称为字符分隔值 因为分隔字符也可以不是逗号 其文件以纯文本形式存储表格数据 数字和文本 纯文本意味着该文件是一个字符序列 不含必须像
  • X86指令:NOP指令

    NOP指令的作用 通常NOP用于对齐指令的地址 NOP指令的特性 因为NOP是X86指令中最短的 只有1byte 处理器执行NOP指令时 不进行任何的操作 不会影响系统的状态 NOP也有其他的用途 1 编程时如果使用了支持lable标记的编
  • javascript函数相关例题

    前言 虽然for也能实现一些简单的 重复操作 但是 比较具有局限性 我们js 里面 也有非常多的相同代码 可能需要大量重复使用 此时我们可以利用函数 一 函数是什么 函数 就是 封装了 一段 可被重复调用执行的 代码块 可以实现大量代码的重
  • 删除git在windows上的凭证

    由于本人安装git的客户端以及开始下载github上的项目代码 第一次输入的账户名以及密码错误 需要删除windows上自己保存的账号密码凭证 我自己的电脑配置 运用命令行打开控制面板也十分方便 快捷键 Win R 打开运行窗口 输入 co
  • vs2010 使用QT

    首先不要使用中文目录 1 下载Qt的安装包和VS2010的Qt插件 2 安装Qt SDK 3 安装Qt的VS开发插件 4 编译Qt Qt默认使用mingw进行编译 如果要使用VS2010开发 需要将Qt重新编译 进入开始菜单Microsof
  • 在VS8里面 fatal error C1083: 无法打开包括文件:“iostream.h”: No such file or directory

    fatal error C1083 无法打开包括文件
  • pointCloudLibrary点云库使用

    pointCloudLibrary点云库使用 准备 下载源码 https github com PointCloudLibrary pcl 这个是pointCloudLibrary 但不包括 Boost Eigen FLANN OpenNI
  • gdb调试子进程

    GDB 是 linux 系统上常用的调试工具 本文介绍了使用 GDB 调试多进程程序的几种方法 并对各种方法进行比较 GDB 是 linux 系统上常用的 c c 调试工具 功能十分强大 对于较为复杂的系统 比如多进程系统 如何使用 GDB
  • 「前端学习」vue入门-井字棋

    1 Vue 学习路线 2 使用 vue cli 创建 vue 项目 注意 vue cli 对应版本 2 1 创建项目 在当前目录下创建项目 vue create 注意 项目文件名不能由大写 2 2 配置 3 Vue 组件 不成问的规定 默认
  • CentOS 安装 Docker 和 DockerCompose,超详细

    0 安装Docker Docker 分为 CE 和 EE 两大版本 CE 即社区版 免费 支持周期 7 个月 EE 即企业版 强调安全 付费使用 支持周期 24 个月 Docker CE 分为 stable test 和 nightly 三
  • [885]Tensorflow设置CUDA_VISIBLE_DEVICES来控制GPU的使用

    os environ CUDA DEVICE ORDER PCI BUS ID 按照PCI BUS ID顺序从0开始排列GPU设备 os environ CUDA VISIBLE DEVICES 0 设置当前使用的GPU设备仅为0号设备 设
  • Java:关于Java中的线程中断的几种方法

    Java 关于Java中的线程中断的几种方法 1 使用线程的stop 来中断线程 2 使用线程的interrupt 来中断线程 3 通过共享变量来控制 使用线程的stop 来中断线程 这种方式是直接调用线程的stop 方法 可以直接让线程终