当前位置: 首页 > news >正文

interrupt、interrupted、isInterrupted方法详解

interrupt方法的源码:

public void interrupt() {if (this != Thread.currentThread())checkAccess();synchronized (blockerLock) {Interruptible b = blocker;if (b != null) {interrupt0();  //仅仅对当前线程的中断位进行标记b.interrupt();return;}}interrupt0();     // Just to set the interrupt flag
}

源码说明:
private volatile Interruptible blocker;
private native void interrupt0();
变量blocker表示中断状态(interrupt status),blocker的值默认是null。 interrupt0()方法是本地方法,其作用是仅仅对当前线程的中断位进行标记。线程的中断标志位默认是false,interrupt0()方法将线程的中断标志位设置为true,设置线程的中断状态。清除线程的中断状态,就是将中断标志位设置为false。

当线程调用interrupt方法时,会进入到同步代码块中,由于blocker==null,所以不执行if语句中的代码,而是调用interrupt0()方法,将线程的中断标志位设置为true。所以调用interrupt方法不能中断线程,只是设置线程的中断状态

调用sleep、wait或join等方法的线程,如果再调用interrupt方法,将会抛出InterruptedException异常,或者调用interrupt方法的线程,如果再调用sleep、wait或join等方法,也会抛出InterruptedException异常。

interrupted和isInterrupted方法的源码:

public static boolean interrupted() {return currentThread().isInterrupted(true);
}public boolean isInterrupted() {return isInterrupted(false);
}private native boolean isInterrupted(boolean ClearInterrupted);

interruptedisInterrupted方法的相同点都是判断线程的中断状态(interrupted status)是否被设置(即标志位是否为true),若被设置返回true,否则返回false。区别有两点:一:前者是static方法,调用者是current thread,而后者是普通方法,调用者是this thread。二:它们其实都调用了Java中的一个native方法isInterrupted(boolean ClearInterrupted); 不同的是前者传入了参数true,后者传入了false,意义就是:前者将清除线程的interrupt state(将线程的中断标志位设置为false),后者对线程的interrupt state没有影响。

public void interrupt();

向线程发送中断请求,线程的中断标志位将被设置为true。如果线程在调用 Object 类的 wait()、wait(long) 或 wait(long, int) 方法,或者Thread类的join()、join(long)、join(long, int)、sleep(long) 或 sleep(long, int) 方法过程中受阻,将抛出InterruptedException异常,且线程的中断状态将被清除。

调用interrupt方法是在线程中打了一个停止标志,并不是真的停止线程。其作用是中断此线程此线程不一定是当前线程,而是指调用该方法的Thread实例所代表的线程),但实际上只是给线程设置一个中断标志,线程仍会继续运行。可通过interrupted和isInterrupted方法判断中断标志,进而结束线程。此线程是指调用interrupt方法的线程,如Thread t = new Thread();t.interrupt();线程t调用了interrupt方法,所以此线程就是指线程t

public static boolean interrupted();

如果当前线程已经中断,则返回 true;否则返回 false。

interrupted方法的作用是测试当前线程是否被中断(检查中断标志),返回一个boolean并清除中断状态。由于第一次调用interrupted方法时,中断状态已经被清除,第二次再调用interrupted方法时将返回一个false。在哪个线程中调用了interrupted方法,该线程就是当前线程,如在main线程中有如下语句,Thread t = new Thread();t.interrupted();虽然是线程t调用了interrupted方法,但是,是在main线程中调用的interrupted方法,main线程就是当前线程

public boolean isInterrupted();

如果此线程已经中断,则返回 true;否则返回 false。

测试线程是否已经中断,线程的中断状态不受该方法的影响。作用是只测试此线程是否被中断,不清除中断状态。此线程是指调用isInterrupted方法的线程,如在main线程中有如下语句,Thread t = new Thread();t.isInterrupted();即使是在main线程中,但线程t调用了isInterrupted方法,所以此线程就是指线程t

interrupted与isInterrupted方法的区别:interrupted方法是判断当前线程是否被中断,并清除中断状态,而isInterrupted方法是判断此线程是否被中断,不清除中断状态。

示例:

public class MyThread extends Thread {@Overridepublic  void run() {for (int i = 0; i < 10; i++) {System.out.println("i="+(i+1));}}
}public class Test{public static void main(String[] args ) {MyThread thread=new MyThread();thread.start();thread.interrupt();System.out.println("第一次调用thread.isInterrupted():"+thread.isInterrupted());System.out.println("第二次调用thread.isInterrupted():"+thread.isInterrupted());//测试interrupted()函数System.out.println("第一次调用thread.interrupted():"+thread.interrupted());System.out.println("第二次调用thread.interrupted():"+thread.interrupted());System.out.println("thread是否存活:"+thread.isAlive());}
}

测试结果如下所示:

thread线程调用了interrupt方法,并没有使thread线程立即中断,只是将thread线程的中断标志设置为true(线程的中断状态被设置),通过thread.isInterrupted方法判断线程的中断状态是否被设置,若被设置了,则返回true,否则返回false。从输出结果看,可能会有疑惑,为什么后面两个interrupted方法输出的都是false,而不是预料中的一个true一个false?注意!!!这是一个坑!!!上面说到,interrupted方法测试的是当前线程是否被中断,这里当前线程是main线程,而thread.interrupt中断的是thread线程,这里的此线程就是thread线程。所以当前线程main从未被中断过,尽管interrupted方法是以thread.interrupted的形式被调用,但它检测的仍然是main线程而不是检测thread线程,所以thread.interrupted在这里相当于main.interrupted。

若调用sleep()而使线程处于阻塞状态,这时调用interrupt()方法,会抛出InterruptedException,从而使线程提前结束阻塞状态,退出阻塞代码。为什么

1.默认blocker=null; ®1

2.调用方法“interrupt0();”将会导致该线程的中断状态将被设置(JDK文档中术语)”®2

3.再次调用“interrupt0();”将会导致其中断状态将被清除(JDK文档中术语)”®3

异常其实是interrupt()抛出的,而不是sleep()抛出的。


http://www.mrgr.cn/news/65005.html

相关文章:

  • 【Git】Git 远程仓库命令详解
  • 【论文阅读】Associative Alignment for Few-shot Image Classification
  • Zabbix监控架构
  • git入门教程9:配置Git钩子
  • Python pyautogui库:自动化操作的强大工具
  • 批发订货系统的设计、开发及源码实现(PHP + MySQL)
  • WPF+MVVM案例实战(二十一)- 制作一个侧边弹窗栏(CD类)
  • LeetCode 0685.冗余连接 II:并查集(和I有何不同分析)——详细题解(附图)
  • Docker容器消耗资源过多导致宿主机死机解决方案
  • 发现不为人知的AI宝藏:深藏功与名! —— 《第十期》
  • js逆向-模拟加密
  • Linux的IP网路命令: 用于显示和操作网络接口(网络设备)的命令ip link详解
  • masm汇编字符串输出演示
  • ChatGPT 和 RAG(检索增强生成)的区别;ChatGPT 和 RAG 的联系
  • AIGC对传统内容创作行业的冲击
  • 【Linux】make/makefile/gdb调试技巧/进度条小程序
  • 无人机场景 - 目标检测数据集 - 夜间车辆检测数据集下载「包含VOC、COCO、YOLO三种格式」
  • 【蓝队技能】【溯源反制】反打红队-蜜罐工具反制
  • SpringBoot集成ELK收集日志管理
  • PyQt5入门级超详细教程中篇
  • 【论文笔记】Dense Connector for MLLMs
  • 引起what(): basic_string::_M_replace_aux问题的一个原因以及解决方法
  • Mysql开发规范
  • Java项目实战II基于Spring Boot的文理医院预约挂号系统的设计与实现(开发文档+数据库+源码)
  • nfs作业
  • 目录的简介和rest api规范