Java中线程中断的几种方法小结

 更新时间:2023年12月20日 15:58:10   作者:爪哇码农  
在Java中,线程中断是一种协作机制,它通过设置线程的中断标志位来通知线程需要中断,本文主要介绍了Java中线程中断的几种方法小结,具有一定的参考价值,感兴趣的可以了解一下

使用线程的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修饰的方法

总结

  • public void interrupt() 其中interrupt()是一个实例方法
    它通知目标线程中断,也仅仅是设置目标线程的中断标志位为true.
  • public boolean isInterrupted() 其中isInterrupted()方法也是一个实例方法
    它判断当前线程是否被中断(通过检查中断标志位)并获得中断标志
  • 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("主线程结束");
    }

其运行结果如下

在这里插入图片描述

到此这篇关于Java中线程中断的几种方法小结的文章就介绍到这了,更多相关Java 线程中断内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JAVA实现长连接(含心跳检测Demo)

    JAVA实现长连接(含心跳检测Demo)

    这篇文章主要介绍了JAVA实现长连接(含心跳检测Demo),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-10-10
  • 详解Java ES多节点任务的高效分发与收集实现

    详解Java ES多节点任务的高效分发与收集实现

    ElasticSearch 是一个高可用开源全文检索和分析组件。提供存储服务,搜索服务,大数据准实时分析等。一般用于提供一些提供复杂搜索的应用
    2021-06-06
  • Java Map集合使用方法全面梳理

    Java Map集合使用方法全面梳理

    Map是一种依照键(key)存储元素的容器,键(key)很像下标,在List中下标是整数。在Map中键(key)可以使任意类型的对象。Map中不能有重复的键(Key),每个键(key)都有一个对应的值(value)。一个键(key)和它对应的值构成map集合中的一个元素
    2022-04-04
  • springboot实现yml里的自定义配置方法

    springboot实现yml里的自定义配置方法

    这篇文章主要介绍了springboot实现yml里的自定义配置方法,主要介绍三种,字符串配置,数组配置和带默认值的配置,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-01-01
  • postman中参数和x-www-form-urlencoded传值的区别及说明

    postman中参数和x-www-form-urlencoded传值的区别及说明

    在Postman中,参数传递有多种方式,其中params和x-www-form-urlencoded最为常用,Params主要用于URL中传递查询参数,适合GET请求和非敏感数据,其特点是将参数作为查询字符串附加在URL末尾,适用于过滤和排序等操作
    2024-09-09
  • Java实体类中Set按照对象的某个字段对set排序

    Java实体类中Set按照对象的某个字段对set排序

    这篇文章主要介绍了Java实体类中Set按照对象的某个字段对set排序,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-06-06
  • Java中的静态内部类详解及代码示例

    Java中的静态内部类详解及代码示例

    这篇文章主要介绍了Java中的静态内部类详解及代码示例,具有一定参考价值,需要的朋友可以了解下。
    2017-10-10
  • Java中Request请求转发详解

    Java中Request请求转发详解

    这篇文章主要介绍了Java中Request请求转发详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-07-07
  • 解决Spring配置文件中bean的property属性中的name出错问题

    解决Spring配置文件中bean的property属性中的name出错问题

    这篇文章主要介绍了解决Spring配置文件中bean的property属性中的name出错问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • elasticsearch的zenDiscovery和master选举机制原理分析

    elasticsearch的zenDiscovery和master选举机制原理分析

    这篇文章主要介绍了elasticsearch的zenDiscovery和master选举机制原理分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-04-04

最新评论