https://www.zhihu.com/question/41048032

作者:Intopass
链接:https://www.zhihu.com/question/41048032/answer/89431513
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

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

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

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

Thread thread = new Thread(() -> {while (!Thread.interrupted()) {// do more work.}
});
thread.start();// 一段时间以后
thread.interrupt();

具体到你的问题,Thread.interrupted()清除标志位是为了下次继续检测标志位。
如果一个线程被设置中断标志后,选择结束线程那么自然不存在下次的问题,
而如果一个线程被设置中断标识后,进行了一些处理后选择继续进行任务,
而且这个任务也是需要被中断的,那么当然需要清除标志位了。

作者:大闲人柴毛毛
链接:https://www.zhihu.com/question/41048032/answer/252905837
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

interrupted()是Java提供的一种中断机制,要把中断搞清楚,还是得先系统性了解下什么是中断机制。

什么是中断?

在Java中没有办法立即停止一条线程,然而停止线程却显得尤为重要,如取消一个耗时操作。因此,Java提供了一种用于停止线程的机制——中断。

  • 中断只是一种协作机制,Java没有给中断增加任何语法,中断的过程完全需要程序员自己实现。若要中断一个线程,你需要手动调用该线程的interrupted方法,该方法也仅仅是将线程对象的中断标识设成true;接着你需要自己写代码不断地检测当前线程的标识位;如果为true,表示别的线程要求这条线程中断,此时究竟该做什么需要你自己写代码实现。
  • 每个线程对象中都有一个标识,用于表示线程是否被中断;该标识位为true表示中断,为false表示未中断;
  • 通过调用线程对象的interrupt方法将该线程的标识位设为true;可以在别的线程中调用,也可以在自己的线程中调用。

中断的相关方法

  • public void interrupt()
    将调用者线程的中断状态设为true。
  • public boolean isInterrupted()
    判断调用者线程的中断状态。
  • public static boolean interrupted
    只能通过Thread.interrupted()调用。
    它会做两步操作:
  1. 返回当前线程的中断状态;
  2. 将当前线程的中断状态设为false;

如何使用中断?

要使用中断,首先需要在可能会发生中断的线程中不断监听中断状态,一旦发生中断,就执行相应的中断处理代码。
当需要中断线程时,调用该线程对象的interrupt函数即可。

1.设置中断监听

Thread t1 = new Thread( new Runnable(){public void run(){// 若未发生中断,就正常执行任务while(!Thread.currentThread.isInterrupted()){// 正常任务代码……}// 中断的处理代码……doSomething();}
} ).start();

正常的任务代码被封装在while循环中,每次执行完一遍任务代码就检查一下中断状态;一旦发生中断,则跳过while循环,直接执行后面的中断处理代码。

2.触发中断

t1.interrupt();

上述代码执行后会将t1对象的中断状态设为true,此时t1线程的正常任务代码执行完成后,进入下一次while循环前Thread.currentThread.isInterrupted()的结果为true,此时退出循环,执行循环后面的中断处理代码。

如何安全地停止线程?

stop函数停止线程过于暴力,它会立即停止线程,不给任何资源释放的余地,下面介绍两种安全停止线程的方法。

1.循环标记变量

自定义一个共享的boolean类型变量,表示当前线程是否需要中断。

  • 中断标识
volatile boolean interrupted = false;
  • 任务执行函数
Thread t1 = new Thread( new Runnable(){public void run(){while(!interrupted){// 正常任务代码……}// 中断处理代码……// 可以在这里进行资源的释放等操作……}
} );
  • 中断函数
Thread t2 = new Thread( new Runnable(){public void run(){interrupted = true;}
} );

2.循环中断状态

  • 中断标识
    由线程对象提供,无需自己定义。
  • 任务执行函数
Thread t1 = new Thread( new Runnable(){public void run(){while(!Thread.currentThread.isInterrupted()){// 正常任务代码……}// 中断处理代码……// 可以在这里进行资源的释放等操作……}
} );
  • 中断函数
t1.interrupt();

上述两种方法本质一样,都是通过循环查看一个共享标记为来判断线程是否需要中断,他们的区别在于:第一种方法的标识位是我们自己设定的,而第二种方法的标识位是Java提供的。除此之外,他们的实现方法是一样的。

上述两种方法之所以较为安全,是因为一条线程发出终止信号后,接收线程并不会立即停止,而是将本次循环的任务执行完,再跳出循环停止线程。此外,程序员又可以在跳出循环后添加额外的代码进行收尾工作。

如何处理中断?

上文都在介绍如何获取中断状态,那么当我们捕获到中断状态后,究竟如何处理呢?

  • Java类库中提供的一些可能会发生阻塞的方法都会抛InterruptedException异常,如:BlockingQueue#put、BlockingQueue#take、Object#wait、Thread#sleep。
  • 当你在某一条线程中调用这些方法时,这个方法可能会被阻塞很长时间,你可以在别的线程中调用当前线程对象的interrupt方法触发这些函数抛出InterruptedException异常。
  • 当一个函数抛出InterruptedException异常时,表示这个方法阻塞的时间太久了,别人不想等它执行结束了。
  • 当你的捕获到一个InterruptedException异常后,亦可以处理它,或者向上抛出。
  • 抛出时要注意???:当你捕获到InterruptedException异常后,当前线程的中断状态已经被修改为false(表示线程未被中断);此时你若能够处理中断,则不用理会该值;但如果你继续向上抛InterruptedException异常,你需要再次调用interrupt方法,将当前线程的中断状态设为true。
  • 注意:绝对不能“吞掉中断”!即捕获了InterruptedException而不作任何处理。这样违背了中断机制的规则,别人想让你线程中断,然而你自己不处理,也不将中断请求告诉调用者,调用者一直以为没有中断请求。

Thread.currentThread().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. Java Thread的interrupt方法详解

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

  4. 演示Thread.sleep(100)和Thread.currentThread().isInterrupted()+@Deprecated:将方法标注为废弃的方法...

    package charpter08; public class TestInterrupt01 { public static void main(String[] args) { Processo ...

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

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

  6. Thread.interrupted()与Thread.currentThread().isInterrupted()区别

    背景 今天在研究ThreadPoolExecutor源码时,在runWorker(Worker w)的方法中有一个判断条件分别用到了Thread.interrupted()和Thread.curren ...

  7. Thread.currentThread().getContextClassLoader() 和 Class.getClassLoader()区别

    查了一些资料也不是太明白两个的区别,但是前者是最安全的用法 打个简单的比方,你一个WEB程序,发布到Tomcat里面运行. 首先是执行Tomcat org.apache.catalina.startu ...

  8. Thread.currentThread().getContextClassLoader().getResourceAsStream()读取配置文件

    Java中使用的路径,分为两种:绝对路径和相对路径.具体而言,又分为四种: 一.URI形式的绝对资源路径 如:file:/D:/java/eclipse/workspace/j/bin/a URL是U ...

  9. android getid,Process.myTid()和Thread.currentThread().getId()区别

    首先,两个方法都是返回线程ID,但结果是不同的,简单的说 android.os.Process.myTid()是系统级的ID Thread.currentThread().getId()是Java级的 ...

最新文章

  1. js php 实现日历签到_PHP 可能在未来十年内消失?
  2. 赫夫曼树建立c语言源程序编译结果详细解释,哈夫曼树的建立与实现最终版(备份存档)...
  3. ip冲突 scan windows_Linux下IP 冲突查看及解决方法
  4. sublime 正则搜索日语字符
  5. 从双层优化视角理解对抗网络GAN
  6. 2019ug最新版本是多少_宝塔Linux面板7.4.2版本/Windows面板6.8版本请尽快升级到最新版本...
  7. OpenCV积分图函数:integral ()介绍
  8. 【技术专题研究】OSPF的LSA类型
  9. 北京上海深圳杭州地图poi下载
  10. 【有限元分析】提高有限元分析计算精度的h方法和p方法
  11. MySQL必知必会——数据库基础知识和MySQL基本使用
  12. web接入 微信SDK
  13. python获取erp数据_python自学之路-数据读取
  14. 【python设计模式】6、装饰器模式
  15. OpenNi学习笔记
  16. 语音-小度自定义技能
  17. MySQL查询报错Unknown column ‘new_edition‘ in ‘IN/ALL/ANY subquery‘
  18. 洛谷P1562 还是N皇后(DFS+状态压缩+位运算)
  19. 晾衣服,西北大学集训队选拔赛(重现赛)
  20. 什么是Jython?

热门文章

  1. 苹果xr配置_5000元以内苹果手机推荐:11、XS、XSMax怎么选?
  2. php图片无损压缩的问题解决(推荐)
  3. Python入门到精通(4):关系与逻辑表达式
  4. 嵌入式系统词汇速查表,不会时候拿出来看看!(精品收藏)
  5. Maven远程仓库配置(阿里云)
  6. 队列,栈,堆栈,数组,链表特点与区别
  7. 炫‘库’行动-人大金仓有奖征文-挑战国产数据库金仓上k8s(二)
  8. Q-learning学习的一个小例子
  9. Mysql三、数据库面试题+sql语句解析
  10. eos的石墨烯技术是什么