一、interrupt()、isInterrupt()、interrupted()

可以参考我前面的文章4.4.2节:了解多线程的意义和作用

用我自己的描述:

  • interrupt():修改线程的中断状态。如果线程在调用Object类的wait(),wait(long)或wait(long,int)方法,或者该类的join(),join(long),join(long,int),sleep(long),slepp(long,int)方法过程受阻,则其中断状态被清除,它将收到InterruptedException
  • interrupted():测试线程是否被中断,并且将中断状态清除。
  • isInterrupted():测试线程是否给中断,中断状态不受影响

二、interrupt()的作用与使用

一个线程不应该由其他线程来强制中断或停止,而是应该由线程自己自行停止。
所以,Thread.stop, Thread.suspend, Thread.resume 都已经被废弃了。
而 Thread.interrupt 的作用其实也不是中断线程,而是「通知线程应该中断了」,
具体到底中断还是继续运行,应该由被通知的线程自己处理。

具体来说,当对一个线程,调用 interrupt() 时,
① 如果线程处于被阻塞状态(例如处于sleep, wait, join 等状态),那么线程将立即退出被阻塞状态,并抛出一个InterruptedException异常。仅此而已。
② 如果线程处于正常活动状态,那么会将该线程的中断标志设置为 true,仅此而已。被设置中断标志的线程将继续正常运行,不受影响。

interrupt() 并不能真正的中断线程,需要被调用的线程自己进行配合才行。
也就是说,一个线程如果有被中断的需求,那么就可以这样做。
① 在正常运行任务时,经常检查本线程的中断标志位,如果被设置了中断标志就自行停止线程。
② 在调用阻塞方法时正确处理InterruptedException异常。(例如,catch异常后就结束线程。)

三、interrupt()原理

具体可以参考这篇文章:Java多线程之interrupt()的深度研究

重点贴一下:

四、调用interrupt()抛出异常的情况

对于interrupt()方法,根据官方文档:

  • 如果指定线程调用了interrupt(),并且该线程不处于被sleep,wait,join的状态,那么一切正常,不会抛出调用InterruptException异常,就不会清除中断标志位。如果此时再调用isInterrupted()就会返回true。
  • 如果指定线程调用了interrupt()时,而指定线程正处于阻塞状态sleep,wait,join...线程自己就会立即抛InterruptException异常。
    • 原本“interrupt标志位”应该是true(因为之前调用了interrupt()),也会被清除变为false。如果再调用isInterrupted()返回false。
    • 如果你的程序不捕获这个异常,线程就会异常终止,进入TERMINATED状态;如果你的程序捕获了这个异常,那么程序就会继续执行catch语句块(可能还有finally语句块)以及以后的代码。
    • 需要注意的是,InterruptedException是线程自己从内部抛出的,并不是interrupt()方法抛出的。对某一线程调用interrupt()时,如果该线程正在执行普通的代码,那么该线程根本就不会抛出InterruptedException。但是,一旦该线程进入到wait()/sleep()/join()后,就会立刻抛出InterruptedException。

Q:为什么当指定线程在被阻塞状态(sleep, wait)时,调用interrupt(),要立即抛出InterruptException异常,并清除“interrupt标志位”(从true变为false)

A:【本答案不是很严谨,请大家斧正】线程在被阻塞过程中,可能掌握着某种资源。如果线程刚从阻塞回来,“interrupt标志位”就是true,很可能(视用户自定义的代码而定)线程就真准备中断,没有给程序任何回收资源的时间。因此先取消标志位,回收下资源然后视情况再决定是否真的interrupt。

本人赘言:

注,synchronized在获锁的过程中是不能被中断的,意思是说如果产生了死锁,则不可能被中断。与synchronized功能相似的reentrantLock.lock()方法也是一样,它也不可中断的,即如果发生死锁,那么reentrantLock.lock()方法无法终止,如果调用时被阻塞,则它一直阻塞到它获取到锁为止。但是如果调用带超时的tryLock方法reentrantLock.tryLock(long timeout, TimeUnit unit),那么如果线程在等待时被中断,将抛出一个InterruptedException异常,这是一个非常有用的特性,因为它允许程序打破死锁。你也可以调用reentrantLock.lockInterruptibly()方法,它就相当于一个超时设为无限的tryLock方法。

五、如何正确中断线程

如果中断sleep,wait,join等,就会抛InterruptException异常,就会清除中断标志位,那么这种情况应该怎么处理呢?为了保证数据的一致性和完整性,我们需要用Thread.interrupt()方法再次中断自己,置上中断标志位。例子如下:

@Test
public void testInterrupt() throws InterruptedException {Thread t1 = new Thread() {public void run() {while (true) {if (Thread.currentThread().isInterrupted()) {System.out.println("Interruted!");break;}try {Thread.sleep(2000); // 睡眠时中断会清除中断标志位} catch (InterruptedException e) {// 如果少了下面这句,这个线程虽然在外面中断,但是只要中断睡眠中的进程// 就会清除中断标志位,仍然处于无限循环,会竞争CPU资源Thread.currentThread().interrupt(); // 再次中断置上中断标记}Thread.yield();}}};t1.start();       //t1 thread would runningThread.sleep(200);//sleep main threadt1.interrupt();   //after main thread wake up, would plan to interrupt t1 thread
}

也可以把异常抛出,在run方法外面判断是否继续设置中断状态:thread.isInterrupted()。

interrupt()官方文档

中断线程。

如果当前线程没有中断它自己(这在任何情况下都是允许的),则该线程的 checkAccess 方法就会被调用,这可能抛出 SecurityException。

如果线程在调用 Object 类的 wait()、wait(long) 或 wait(longint) 方法,或者该类的 join()、join(long)、join(longint)、sleep(long) 或 sleep(longint) 方法过程中受阻,则其中断状态将被清除,它还将收到一个 InterruptedException。

如果该线程在可中断的通道上的 I/O 操作中受阻,则该通道将被关闭,该线程的中断状态将被设置并且该线程将收到一个 ClosedByInterruptException。

如果该线程在一个 Selector 中受阻,则该线程的中断状态将被设置,它将立即从选择操作返回,并可能带有一个非零值,就好像调用了选择器的 wakeup 方法一样。

如果以前的条件都没有保存,则该线程的中断状态将被设置。

中断一个不处于活动状态的线程不需要任何作用。

抛出:

SecurityException - 如果当前线程无法修改该线程

第四章、第五章、第六章参考:https://www.cnblogs.com/frankcui/p/12437463.html

说说Thread的interrupt()相关推荐

  1. Thread.currentThread.interrupt()

    Thread.currentThread.interrupt() 只对阻塞线程起作用, 当线程阻塞时,调用interrupt方法后,该线程会得到一个interrupt异常,可以通过对该异常的处理而退出 ...

  2. Thread.currentThread().interrupt()和Thread.interrupted()和Thread.currentThread().isInterrupted()

    Thread.interrupted() 可以返回当前标志位并使标志位为false Thread.currentThread().interrupt() 可以使标志位置为true Thread.cur ...

  3. Thread的interrupt()方法排雷

    有些时候会需要在线程的run()方法返回之前手动中止线程,这时就会用到Thread的interrupt()实例方法.这个方法的使用有许多坑,稍不注意就会出错.本文将对这个方法以及与它相关的知识点进行一 ...

  4. Java Thread的interrupt方法详解

    Java Thread的interrupt方法详解 一.概述 interrupt方法的目的是给线程发出中断信号,但是不保证线程真的会中断 中断一个线程只是为了引起该线程的注意,被中断线程可以决定如何应 ...

  5. Thread中interrupt()interrupted()和isInterrupted()的区别

    2019独角兽企业重金招聘Python工程师标准>>> 在java线程中,线程的状态分为6种.官方文档的解释是: /*** Thread state for a thread whi ...

  6. 一心多用多线程-Thread的interrupt机制

    使Thread中断的方式有很多种,比如调用stop()方法进行中断,但stop()方法存在线程的安全性问题,java api已经不推荐使用,那么我们想要让一个线程停止,我们可以使用java里面的int ...

  7. 简述Thread的interrupt()、interrupted()及isInterrupted()的区别

    前言 在java Thread类中,我们会看到interrupt().interrupted()及isInterrupted(),在大多数情况下,我们都不会使用到它们,但是有一个Interrupted ...

  8. Thread.currentThread().interrupt()

    https://www.zhihu.com/question/41048032 作者:Intopass 链接:https://www.zhihu.com/question/41048032/answe ...

  9. LockSurport中park()、unpark()和Thread中interrupt()的区别与联系

    park().unpark()简单说明: LockSurport中park()执行时会判断当前线程是否有"许可"(初始化的线程没有"许可"),若没有" ...

  10. (转)Thread的中断机制(interrupt)

    先看收集了别人的文章,全面的了解下java的中断: 中断线程 线程的thread.interrupt()方法是中断线程,将会设置该线程的中断状态位,即设置为true,中断的结果线程是死亡.还是等待新的 ...

最新文章

  1. EPSON机械手建立工具坐标系方法
  2. 形态学滤波:腐蚀与膨胀(浅谈)
  3. INSERT IGNORE 与INSERT INTO的区别
  4. 手机信号放大器 让手机信号增强的办法
  5. 「SLAM」十四讲:第1讲 预备知识
  6. 练习系列 - 5、求子数组的最大和
  7. 全局预处理与执行,作用域与作用域链
  8. 前端学习(2981):Json格式转换
  9. php函数方法属性吗,为什么PHP属性不允许使用函数?
  10. 趣题一则:寻找那扇门
  11. Day2 - Python基础2作业【购物车程序】
  12. Bailian1183 POJ1183 反正切函数的应用【迭代计算】
  13. access根据所属院系修改学号_2016年计算机二级《Access》冲刺试题及答案
  14. 超详细的CentOS7的下载安装配置教程
  15. 关闭windows端口的批处理命令
  16. Index Notation
  17. 《程序员》沉痛悼念王江民先生
  18. Android 设置gif动态桌面
  19. php转义和反转,PHP转义,反转义
  20. 阿里云视频直播开发----java

热门文章

  1. PyTorch搭建AlexNet模型(在CIFAR10数据集上准确率达到了85%)
  2. java上传图片裁剪_浅谈java图片上传之剪切
  3. 将大于2的偶数分解成两个素数之和
  4. mysql--id主键列乱了之后,重新排序
  5. php5.6软件下载,【PHP下载】PHP for Linux 5.6.6-ZOL软件下载
  6. ajax 单击事件删除,AJAX删除事件与加载数据方法介绍
  7. 泾县高级职业中学计算机专业课程,泾县高级职业中学:以人为本 促可持续发展...
  8. 【机器学习系列】变分推断第一讲:Variational Inference背景和用途
  9. tomcat/redis/dubbo/netty
  10. 【Gym - 101234A】Hacker Cups and Balls【线段树 + 二分答案】