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 线程中断内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解SpringBoot开发案例之整合Dubbo分布式服务

    详解SpringBoot开发案例之整合Dubbo分布式服务

    这篇文章主要介绍了详解SpringBoot开发案例之整合Dubbo分布式服务,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-10-10
  • 选择java的理由:java之父访谈实录

    选择java的理由:java之父访谈实录

    选择java的理由:java之父访谈实录...
    2006-12-12
  • Java线程间协作wait、notify和notifyAll详解

    Java线程间协作wait、notify和notifyAll详解

    这篇文章主要介绍了Java线程间协作wait、notify和notifyAll详解,在 Java 中可以用 wait、notify 和 notifyAll 来实现线程间的通信,尽管关于wait和notify的概念很基础,它们也都是Object类的函数,但用它们来写代码却并不简单,,需要的朋友可以参考下
    2023-10-10
  • SpringBoot基于Redis实现生成全局唯一ID的方法

    SpringBoot基于Redis实现生成全局唯一ID的方法

    在项目中生成全局唯一ID有很多好处,生成全局唯一ID有助于提高系统的可用性、数据的完整性和安全性,同时也方便数据的管理和分析,所以本文给大家介绍了SpringBoot基于Redis实现生成全局唯一ID的方法,文中有详细的代码讲解,需要的朋友可以参考下
    2023-12-12
  • 在java代码中获取JVM参数的方法

    在java代码中获取JVM参数的方法

    下面小编就为大家带来一篇在java代码中获取JVM参数的方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-01-01
  • Spring Boot Security认证之Redis缓存用户信息详解

    Spring Boot Security认证之Redis缓存用户信息详解

    本文介绍了如何使用Spring Boot Security进行认证,并通过Redis缓存用户信息以提高系统性能,通过配置RedisUserDetailsManager,我们成功地将用户信息存储到了Redis中,并在Spring Security中进行了集成,需要的朋友可以参考下
    2024-01-01
  • 使用javax.sound实现简单音频播放

    使用javax.sound实现简单音频播放

    这篇文章主要为大家详细介绍了使用javax.sound实现简单音频播放,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-03-03
  • Java实现英文猜词游戏的示例代码

    Java实现英文猜词游戏的示例代码

    这篇文章主要介绍了如何用Java编写一个英文猜词游戏,可以用来背英语单词。文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下
    2022-02-02
  • SpringBoot Redisson 集成的实现示例

    SpringBoot Redisson 集成的实现示例

    本文主要介绍了SpringBoot Redisson 集成的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-05-05
  • SpringBoot同时集成Mybatis和Mybatis-plus框架

    SpringBoot同时集成Mybatis和Mybatis-plus框架

    在实际开发中,项目里面一般都是Mybatis和Mybatis-Plus公用,但是公用有版本不兼容的问题,本文主要介绍了Spring Boot项目中同时集成Mybatis和Mybatis-plus,具有一档的参考价值,感兴趣的可以了解一下
    2024-12-12

最新评论