interrupt、interrupted 、isInterrupted 区别
参考链接:
https://blog.csdn.net/z69183787/article/details/25076033
https://blog.csdn.net/zhuyong7/article/details/80852884
《并发编程的艺术》
1、 interrupt
interrupt方法用于中断线程。调用该方法的线程的状态为将被置为"中断"状态。
注意:
线程中断仅仅是设置线程中一个boolean类型的标志符为True,意味着为中断状态(该字段并不是Thread类的字段,并且标志该字段的方法是native方法),并不会停止线程。需要用户自己去监视线程的状态为并做处理。
支持线程中断的方法,如wait、sleep、join(中断后会抛出interruptedException的方法)就是在监视线程的中断状态,一旦线程的中断状态被置为“中断状态”,该线程会立即被唤醒,并抛出中断异常。
从Java的API中可以看到,许多声明抛出InterruptedException的方法(例如Thread.sleep(longmillis)方法)这些方法在抛出InterruptedException之前,Java虚拟机会先将该线程的中断标识位清除,然后抛出InterruptedException,此时调用isInterrupted()方法将会返回false。
2、 interrupted 和 isInterrupted底层实现
2.1 interrupted
-
测试当前线程是否已经中断。线程的中断状态由该方法清除。换句话说,如果连续两次调用该方法,第一次返回true,第二次返回false。(注意当前线程为调用该命令的线程环境,不一定是调用该方法的对象,也并不一定是main线程)
-
为Thread的静态方法,一般Thread.interrupted()即可(也可以用自己创建的对象来调用,效果相同,但一般不这么做,容易给代码的阅读增加复杂度)。
扩展:静态方法不能被重写,但是继承该类的类还是可以重新定义该方法,但是不具有多态特性。https://blog.csdn.net/gao_zhennan/article/details/72892946
https://blog.csdn.net/ghgzczxcvxv/article/details/43966243
实现:
public static boolean interrupted() { return currentThread().isInterrupted(ClearInterrupted: true); }
2.2 isInterrupted
-
测试调用该方法的对象是否已经中断。线程的中断状态不受该方法的影响。
-
为实例方法,由创建的线程对象,或者thread.currentThread()来调用。
实现:
public boolean isInterrupted() { return isInterrupted(ClearInterrupted: false) }
2.3 对比
-
interrupted 是作用于当前线程,isInterrupted 是作用于调用该方法的线程对象所对应的线程。(线程对象对应的线程不一定是当前运行的线程。例如我们可以在A线程中去调用B线程对象的isInterrupted方法。)
-
这两个方法最终都会调用同一个方法,只不过参数一个是true,一个是false。只有当前线程才能清除自己的中断位(对应interrupted()方法)
先来看一看被调用的方法 isInterrupted(boolean arg)的定义:
private native boolean isInterrupted( boolean ClearInterrupted); 原来这是一个本地方法,看不到源码。不过没关系,通过参数名我们就能知道,这个参数代表是否要清除状态位。
如果这个参数为true,说明返回线程的状态位后,要清掉原来的状态位(恢复成原来情况)。这个参数为false,就是直接返回线程的状态位。
3、 实例解析
1.
public static void main(String[] args){ MyThread myThread = new MyThread(); myThread.start(); myThread.interrupt(); System.out.println("第一次返回值:"+Thread.interrupted()); System.out.println("第二次返回值:"+Thread.interrupted()); }
结果: false false
中断的线程是自己创建的myThread线程,调用的interrupted()是判断当前线程的中断状态,当前线程是main线程,我根本没有中断过main线程,所以2次调用均返回“false”
2.
public static void main(String[] args){ MyThread myThread = new MyThread(); myThread.start(); Thread.currentThread().interrupt(); System.out.println("第一次返回值:"+Thread.interrupted()); System.out.println("第二次返回值:"+Thread.interrupted()); }
结果: true false
Thread.currentThread().interrupt()将当前线程main线程设置为中断状态,所以第1次调用结果返回“true”。 由源码可知interrupted()会重置中断状态,所以第一次调用之后把中断状态给重置了,从中断状态重置为非中断状态,所以第2次调用的结果返回“false”
3.
public static void main(String[] args){ MyThread myThread = new MyThread(); myThread.start(); myThread.interrupt(); System.out.println("第一次返回值:"+myThread.isInterrupted()); System.out.println("第二次返回值:"+myThread.isInterrupted()); }
结果: true true
由源码可知isInterrupted()不会重置中断状态,所以第一次调用之后没有把中断状态给重置(从中断状态重置为非中断状态),所以2次调用的结果都是“true”
4.
public static void main(String[] args){ MyThread myThread = new MyThread(); myThread.start(); myThread.interrupt(); System.out.println("第一次返回值:"+Thread.currentThread().isInterrupted()); System.out.println("第二次返回值:"+Thread.currentThread().isInterrupted()); }
结果:false false
一次调用Thread.currentThread().isInterrupted()等效于Thread.interrupted()
中断的线程是我们自己创建的myThread线程,我调用的isInterrupted(),由上面源码可知是判断执行该方法的对象所表示线程的中断状态,也就是main的中断状态,我压根没有中断main线程,所以理所当然2次调用结果都返回“false”
5.
public static void main(String[] args){ MyThread myThread = new MyThread(); myThread.start(); Thread.currentThread().interrupt(); System.out.println("第一次返回值:"+Thread.currentThread().isInterrupted()); System.out.println("第二次返回值:"+Thread.currentThread().isInterrupted()); }
结果:true true
中断的线程是当前线程(main线程),我调用的isInterrupted(),由上面源码可知是判断执行该方法的对象所表示线程的中断状态,也就是main的中断状态,所以第1次调用结果返回“true”,
因为源码内部调用isInterrupted() 参数传的false,不会重置main线程的中断状态,所以第2次调用还是返回”true”
6 .
public class Interrupted { public static void main(String[] args) throws Exception { // sleepThread不停的尝试睡眠 Thread sleepThread = new Thread(new SleepRunner(), "SleepThread"); sleepThread.setDaemon(true); // busyThread不停的运行 Thread busyThread = new Thread(new BusyRunner(), "BusyThread"); busyThread.setDaemon(true); sleepThread.start(); busyThread.start(); // 休眠5秒,让sleepThread和busyThread充分运行 TimeUnit.SECONDS.sleep(5); sleepThread.interrupt(); busyThread.interrupt(); System.out.println("SleepThread interrupted is " + sleepThread.isInterrupted()); System.out.println("BusyThread interrupted is " + busyThread.isInterrupted()); // 防止sleepThread和busyThread立刻退出 SleepUtils.second(2); } static class SleepRunner implements Runnable { @Override public void run() { while (true) { SleepUtils.second(10); } } } static class BusyRunner implements Runnable { @Override public void run() { while (true) { } } } }
结果:
SleepThread interrupted is false
BusyThread interrupted is true
从结果可以看出,抛出InterruptedException的线程SleepThread,其中断标识位被清除了,而一直忙碌运作的线程BusyThread,中断标识位没有被清除。
来源:https://www.cnblogs.com/Stephanie-boke/p/12319847.html