前言
Java多线程中的中断,大家应该不生疏。然而,Thread.java中的三个中断相干函数interrupt(),isInterrupted(),interrupted(),你都真正分明它们之前的区别吗?明天就来聊聊这个话题。
区别
public void interrupt():中断线程,例如,当线程A运行时,线程B能够调用A.interrupt()办法,来设置线程A的中断标记为true,而后线程B立刻返回。留神,这里仅仅是设置标记,线程A理论并没有被中断,它会持续往下执行。然而有一种状况,如果线程A调用了wait系列函数、join办法或者sleep办法而被阻塞挂起,这时候线程B调用A.interrupt()办法时,线程A会在调用wait/join/sleep办法处抛出InterruptedException异样而返回。
public boolean isInterrupted():检测以后线程是否被中断,如果是返回true,否返回false。
public static boolean interrupted():也是检测以后线程是否被中断,是返回true,否返回false,它与isInterrupted不同的是,如果被中断了,返回true的同时会革除中断标记(即重置中断标记为false),并且能够看到它是一个静态方法,能够间接Thread.interrupted()调用,下面2个是一般办法,须要拿到线程实例调用。
能够翻下三者的源码:
interrupt()
public void interrupt() { if (this != Thread.currentThread()) checkAccess(); synchronized (blockerLock) { Interruptible b = blocker; if (b != null) { interrupt0(); // Just to set the interrupt flag b.interrupt(this); return; } } interrupt0();}
isInterrupted()
public boolean isInterrupted() { return isInterrupted(false);}
interrupted()
public static boolean interrupted() { return currentThread().isInterrupted(true);}
这里的isInterrupted(boolean)是一个本地办法:
private native boolean isInterrupted(boolean ClearInterrupted);
能够看到,isInterrupted调用它时,传入的参数是false,示意不革除中断标记,而interrupted调用它时,传入的是true,示意要革除中断标记。
举例说明
下面的陈说可能有点形象,没关系,咱们通过一个例子来加深印象,请思考上面的代码顺次输入什么后果?先不要往下翻答案哦!
public class InterruptDemo { public static void main(String[] args) throws InterruptedException { Thread threadOne = new Thread(() -> { for (;;) { // do nothing, just dead cycle } }); // 启动线程1 threadOne.start(); // (1)设置中断标记 threadOne.interrupt(); // (2)获取中断标记 System.out.println("isInterrupted: " + threadOne.isInterrupted()); // (3)获取中断标记并重置 System.out.println("isInterrupted: " + threadOne.interrupted()); // (4)获取中断标记并重置 System.out.println("isInterrupted: " + Thread.interrupted()); // (5)获取中断标记 System.out.println("isInterrupted: " + threadOne.isInterrupted()); // 主线程期待线程1执行结束 threadOne.join(); System.out.println("main thread is over!"); }}
----------------------分割线--------------------
输入后果是:
你答对了吗?是不是跟你料想的有点不同?别急,咱们一一剖析下
第(1)步,主线程调用线程threadOne的interrupt()办法,此时线程threadOne的中断标记为true,因而第1个输入为true,这置信没什么疑难。
第(2)步,主线程调用线程threadOne的interrupted()办法,这步很容易让人误以为是判断线程threadOne是否被中断并且革除标记,然而这是个陷阱!看看interrupted()源码:
它是返回以后线程是否被中断,以后线程是主线程!并不是threadOne!因为threadOne.interrupted()这行代码是在主线程中执行的,所以以后线程是主线程,如果放在threadOne的run()办法里执行,那么以后线程就是threadOne,想明确了吗?回到主题,主线程此前并没有被中断,所以第2个输入false。
第(3)步,也是判断以后线程(主线程)是否被中断,很显然,第3个仍然输入false。
第(4)步,判断线程threadOne是否被中断,因为threadOne先前的中断标记为true,并且isInterrupted()并不会革除中断标记,所以第4个输入仍然为true。
结束语
本文解说了interrupt(),isInterrupted(),interrupted()三者区别,如果不留神的话,这3者很容易混同,心愿通过本文,让大家更好地了解它们之间的区别,也能够在工作的应用过程中加深了解。最初附上一个线程利用中断机制优雅退出的伪代码,在工作中能够这么去用:
public void run() { try { while(!Thread.currentThread().isInterrupted() && condition not satisfied) { // do work } } catch(InterruptedException e) { // thread was interrupted while wait or sleep } finally { // cleanup work, if necessary }}