Java中线程中断的几种方式,你了解吗?

Java中线程,可以使用 interrupt() 方法来实现线程的中断,那么,线程中中断的方式有几种呢?接下来,我们将介绍3种不同的线程中断方式,跟随我们的脚步,一起去看看!


种一棵树最好的时间是10年前,其次就是现在,加油!
                                                                                   --by蜡笔小柯南

第一招:volatile 变量法

使用 volatile 关键字,来保证数据的可见性,在多个线程之间,数据是可见的,代码如下:

public class InterruptTest {

    static volatile boolean flag = false;

    public static void main(String[] args) throws Exception {
        interruptedMethod1();
    }

    private static void interruptedMethod1() throws InterruptedException {
        Thread t1 = new Thread(() -> {
            while (true) {
                if (flag) {
                    System.out.println(Thread.currentThread().getName() + " isInterrupted " + Thread.currentThread().isInterrupted());
                    break;
                }
                System.out.println(Thread.currentThread().getName() + "...");
            }
        });
        t1.start();
        TimeUnit.MILLISECONDS.sleep(1);
        Thread t2 = new Thread(() -> {
            flag = true;
        });
        t2.start();
    }
}

声明 volatile boolean flag = false ,由于在 interruptedMethod1 方法中,分别启动了线程t1,线程t2,为了保证 flag 的值在两个线程间可见,以及保证数据的一致性,所以声明为 volatile.

代码解析:

  1. 创建 t1 线程,while(true) 循环中,根据 flag 的值进行判断,从而得出 t1 线程是否跳出此循环;如果 flag 的值为 true ,则跳出循环,否则,一直打印线程t1的名称
  2. 创建 t2 线程,t2 线程中,将flag的值修改为true,由于flag为多线程可见,所以 t1 线程中判断到了flag的值是true,则执行打印输出语句后,执行break,结束循环

第二招:AtomicBoolean 原子类型

使用原子布尔类型,在多线程环境下对布尔值的读取和设置操作是线程安全的,避免了线程间的冲突和数据不一致的问题‌

public class InterruptTest {

    static AtomicBoolean atomicBoolean = new AtomicBoolean(false);

    public static void main(String[] args) throws Exception {
        interruptedMethod2();
    }

    private static void interruptedMethod2() throws InterruptedException {
        Thread t1 = new Thread(() -> {
            while (true) {
                if (atomicBoolean.get()) {
                    System.out.println(Thread.currentThread().getName() + " isInterrupted " + Thread.currentThread().isInterrupted());
                    break;
                }
                System.out.println(Thread.currentThread().getName() + "...");
            }
        });
        t1.start();
        TimeUnit.MILLISECONDS.sleep(1);
        Thread t2 = new Thread(() -> {
            atomicBoolean.set(true);
        });
        t2.start();
    }
}

代码分析:

  1. 通过调用 get() 方法,获取所设置的 boolean 值,如果值为true,则跳出循环,否则,一直打印线程t1的名称
  2. 线程t2使用 set(true) 方法,修改为true,修改后被t1线程感知到,进入if判断,结束循环

第三招:interrupt() 方法

调用线程的 interrupt() 方法,注意:此方法只是给线程设置一个标识,表示线程可中断,而不是调用此方法后,线程被立即中断,具体是否中断,还需要代码中进行判断处理

isInterrupted() :获取线程的中断状态,如果线程设置了中断标识位,返回true,否则,返回false

public class InterruptTest {

    public static void main(String[] args) throws Exception {
        interruptedMethod3();
    }

    private static void interruptedMethod3() throws InterruptedException {
        Thread t1 = new Thread(() -> {
            while (true) {
                if (Thread.currentThread().isInterrupted()) {
                    System.out.println(Thread.currentThread().getName() + " isInterrupted " + Thread.currentThread().isInterrupted());
                    break;
                }
                System.out.println(Thread.currentThread().getName() + "...");
            }
        });
        t1.start();
        TimeUnit.MILLISECONDS.sleep(1);
        Thread t2 = new Thread(() -> {
            t1.interrupt();
        });
        t2.start();
    }
}

代码分析:

  1. t1 线程中,调用的当前线程的 Thread.currentThread().isInterrupted() 方法,来判断当前线程是否可中断,如果为true,则进入if分支,执行break后结束循环
  2. t2 线程中,调用 t1.interrupt() ,给 t1 线程设置中断标志位为true,t1线程通过 Thread.currentThread().isInterrupted() 获取到的值为true,进入if分支,执行break后结束循环

注意:

Thread中的静态方法,Thread.interrupted ,与 isInterrupted() 方法有区别,静态方法的作用是:返回当前线程的中断标志位,如果当前线程的中断标志为处于true,则返回true,并清除中断标志位的状态,重置为false,这个方法有两个作用,一是将中断标志位返回,二是清除中断标志位的状态


那么,如果连续调用2次这个 Thread.interrupted 方法,会有什么效果呢?

:如果线程没有被调用 interrupt 方法,调用两次返回的都是false;如果线程被调用了 interrupt 方法,则第一次调用返回true,第二次调用返回false



如果你有任何疑问或经验分享,可以在评论区留言哦~~

不管在任何时候,我希望你永远不要害怕挑战,不要畏惧失败。每一个错误都是向成功迈出的一步,每一个挑战都是成长的机会,因为每一次的努力,都会使我们离梦想更近一点。只要你行动起来,任何时候都不算晚。最后,把座右铭送给大家:种一棵树最好的时间是10年前,其次就是现在,加油!共勉 💪。
快来吧 👇👇👇

不论是Java的基础资料,还是那些看似枯燥实则精妙的八股文,这里都有你意想不到的解读方式,让复杂变简单,让枯燥变有趣~

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蜡笔小柯南

多谢投喂,感恩家人

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值