Java中线程,可以使用 interrupt()
方法来实现线程的中断,那么,线程中中断的方式有几种呢?接下来,我们将介绍3种不同的线程中断方式,跟随我们的脚步,一起去看看!
目录
- 第一招:volatile 变量法
- 第二招:AtomicBoolean 原子类型
- 第三招:interrupt() 方法
种一棵树最好的时间是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
.
代码解析:
- 创建
t1
线程,while(true) 循环中,根据flag
的值进行判断,从而得出t1
线程是否跳出此循环;如果flag
的值为true
,则跳出循环,否则,一直打印线程t1的名称 - 创建
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();}
}
代码分析:
- 通过调用
get()
方法,获取所设置的boolean
值,如果值为true,则跳出循环,否则,一直打印线程t1的名称 - 线程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();}
}
代码分析:
t1
线程中,调用的当前线程的Thread.currentThread().isInterrupted()
方法,来判断当前线程是否可中断,如果为true,则进入if分支,执行break后结束循环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的基础资料,还是那些看似枯燥实则精妙的八股文,这里都有你意想不到的解读方式,让复杂变简单,让枯燥变有趣~