关于java:聊聊线程中断interruptisInterruptedinterrupted三者区别

45次阅读

共计 2725 个字符,预计需要花费 7 分钟才能阅读完成。

前言

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}
}

正文完
 0