hread.interrupt()到底意味着什么
首先,一个线程不应该由其他线程来强制中断或停止,而是应该由线程自己自行停止。
所以,Thread.stop, Thread.suspend, Thread.resume 都已经被废弃了。
而 Thread.interrupt 的作用其实也不是中断线程,而是「通知线程应该中断了」,
具体到底中断还是继续运行,应该由被通知的线程自己处理。
具体来说,当对一个线程,调用 interrupt() 时,
① 如果线程处于被阻塞状态(例如处于sleep, wait, join 等状态),那么线程将立即退出被阻塞状态,并抛出一个InterruptedException异常。仅此而已。
② 如果线程处于正常活动状态,那么会将该线程的中断标志设置为 true,仅此而已。被设置中断标志的线程将继续正常运行,不受影响。
interrupt() 并不能真正的中断线程,需要被调用的线程自己进行配合才行。
也就是说,一个线程如果有被中断的需求,那么就可以这样做。
① 在正常运行任务时,经常检查本线程的中断标志位,如果被设置了中断标志就自行停止线程。
② 在调用阻塞方法时正确处理InterruptedException异常。(例如,catch异常后就结束线程。)
interrupt()方法:对目标线程发送中断请求,看其源码会发现最终是调用了一个本地方法实现的线程中断;
interrupted()方法:返回目标线程是否中断的布尔值(通过本地方法实现),且返回后会重置中断状态为未中断=false;
isInterrupted()方法:该方法返回的是线程中断与否的布尔值(通过本地方法实现),不会重置中断状态;
示例1(中断失败) /**
* 微信公众号:Java技术栈
*/
private static void test1() {
Thread thread = new Thread(() -> {
while (true) {
Thread.yield();
}
});
thread.start();
thread.interrupt();
}
请问示例1中的线程会被中断吗?答案:不会,因为虽然给线程发出了中断信号,但程序中并没有响应中断信号的逻辑,所以程序不会有任何反应。继续原样执行。跟没有中断是一样的。
示例2:(中断成功) /**
* 微信公众号:Java技术栈
*/
private static void test2() {
Thread thread = new Thread(() -> {
while (true) {
Thread.yield(); // 响应中断
if (Thread.currentThread().isInterrupted()) {
System.out.println("Java技术栈线程被中断,程序退出。");
return;
}
}
});
thread.start();
thread.interrupt();
}
我们给示例2加上了响应中断的逻辑,程序接收到中断信号打印出信息后返回退出。return退出。
示例3(中断失败) /**
* 微信公众号:Java技术栈
*/
private static void test3() throws InterruptedException {
Thread thread = new Thread(() -> {
while (true) {
// 响应中断
if (Thread.currentThread().isInterrupted()) {
System.out.println("Java技术栈线程被中断,程序退出。");
return;
} try {
Thread.sleep();
} catch (InterruptedException e) {
System.out.println("Java技术栈线程休眠被中断,程序退出。");
}
}
});
thread.start();
Thread.sleep();
thread.interrupt();
}
可以看出 sleep() 方法被中断后会清除中断标记,所以循环会继续运行。
示例4(中断成功) /**
* 微信公众号:Java技术栈
*/
private static void test4() throws InterruptedException {
Thread thread = new Thread(() -> {
while (true) {
// 响应中断
if (Thread.currentThread().isInterrupted()) {
System.out.println("Java技术栈线程被中断,程序退出。");
return;
} try {
Thread.sleep();
} catch (InterruptedException e) {
System.out.println("Java技术栈线程休眠被中断,程序退出。");
Thread.currentThread().interrupt();
}
}
});
thread.start();
Thread.sleep();
thread.interrupt();
}
示例4全部信息输出并正常退出,只是在 sleep() 方法被中断并清除标记后手动重新中断当前线程,然后程序接收中断信号返回退出。
我们的系统肯定有些线程为了保证业务需要是要常驻后台的,一般它们不会自己终止,需要我们通过手动来终止它们。我们知道启动一个线程是start方法,自然有一个对应的终止线程的stop方法,通过stop方法可以很快速、方便地终止一个线程。
通过注解@Deprecated看出stop方法被标为废弃的方法,jdk在以后的版本中可能被移除,不建议大家使用这种API。
那为什么这么好的一个方法怎么不推荐使用,还要标注为废弃呢?
假设有这样的一个业务场景,一个线程正在处理一个复杂的业务流程,突然间线程被调用stop而意外终止,这个业务数据还有可能是一致的吗?这样是肯定会出问题的,stop会释放锁并强制终止线程,造成执行一半的线程终止,带来的后果也是可想而知的,这就是为什么jdk不推荐使用stop终止线程的方法的原因,因为它很暴力会带来数据不一致性的问题。
正因为stop方法太过暴力,所以一般不推荐使用,除非你非常清楚你自己的业务场景,用stop终止不会给你的业务带来影响。
说了这么多,那如何优雅地终止一个线程呢?看看下面的程序。
其实也不难,只需要添加一个变量,判断这个变量在某个值的时候就退出循环,这时候每个循环为一个整合不被强行终止就不会影响单个业务的执行结果。
hread.interrupt()到底意味着什么的更多相关文章
- Java并发专题(一)认识线程
1.1 认识线程 线程是轻量级进程,也是程序执行的一个路径,每一个线程都有自己的局部变量表.程序计数器(指向正在执行的指令指针)以及各自的生命周期,现代操作系统中一般不止一个线程在运行.比如说,当我们 ...
- java并发编程(五)----(JUC)ReentrantLock
上一节我们了解了Lock接口的一些简单的说明,知道Lock锁的常用形式,那么这节我们正式开始进入JUC锁(java.util.concurrent包下的锁,简称JUC锁).下面我们来看一下Lock最常 ...
- 关于InterruptedException的两篇博文的转载
博文一:https://www.jianshu.com/p/a8abe097d4ed InterruptedException异常 在了解InterruptedException异常之前应该了解以下的 ...
- HackerNews——《Pokemon Go玩家存在巨大的安全风险》
译者注:原文来自HackerNews,首发tumblr,标题为Pokemon Go is a huge security risk.作者Adam Reeve,附一张这个胖子的帅照 (正文)之所以会 ...
- 如何设计一门语言(七)——闭包、lambda和interface
人们都很喜欢讨论闭包这个概念.其实这个概念对于写代码来讲一点用都没有,写代码只需要掌握好lambda表达式和class+interface的语义就行了.基本上只有在写编译器和虚拟机的时候才需要管什么是 ...
- 【转】漫谈iOS程序的证书和签名机制
转自:漫谈iOS程序的证书和签名机制 接触iOS开发半年,曾经也被这个主题坑的摸不着头脑,也在淘宝上买过企业证书签名这些服务,有大神都做了一个全自动的发布打包(不过此大神现在不卖企业证书了),甚是羡慕 ...
- Java线程并发:知识点
Java线程并发:知识点 发布:一个对象是使它能够被当前范围之外的代码所引用: 常见形式:将对象的的引用存储到公共静态域:非私有方法中返回引用:发布内部类实例,包含引用. 逃逸:在对象尚未准备 ...
- 漫谈iOS程序的证书和签名机制
接触iOS开发半年,曾经也被这个主题坑的摸不着头脑,也在淘宝上买过企业证书签名这些服务,有大神都做了一个全自动的发布打包(不过此大神现在不卖企业证书了),甚是羡慕和崇拜.于是,花了一点时间去研究了一下 ...
- Guava学习笔记(1):Optional优雅的使用null
转自:http://www.cnblogs.com/peida/archive/2013/06/14/Guava_Optional.html 参考:[Google Guava] 1.1-使用和避免nu ...
随机推荐
- Winfrom devexpress 通用权限框架
毕业到现在也快两年了,手上的项目也有好几个,但总感觉不是狠理想,近来把手上杂七杂八的项目整理了一下,结合各个项目的优点,重新开发了一套winfrom+devexpress 通用权限(CS)框架(BS版 ...
- PIE创建带压缩的栅格数据集
这段时间我一直在研究如何用PIE创建带压缩的栅格数据集,由于我在比赛中使用的原始影像大小普遍都在300M以上,软件加载较慢,因此希望能对原始影像进行压缩,加快加载时间. 首先,该方法的关键是修改Dat ...
- js中this绑定方式及如何改变this指向
this的绑定方式基本有以下几种: 隐式绑定 显式绑定 new 绑定 window 绑定 箭头函数绑定 隐式绑定 第一个也是最常见的规则称为 隐式绑定. var a = { str: 'hello', ...
- Hybris Storefront里产品图片显示不出来的分析方法
在Hybris Backoffice里新建一个product,维护了一些图片信息,然而在Storefront上进行搜索时,无论结果列表,还是产品明细页面里,都没有对应的图片可以显示. 我的排查方法是, ...
- java获取客户端请求IP地址(公网ip)
之前写了一个获取ip地址的方法,但是放网上一查显示此Ip地址是局域网ip地址,要是想获取请求端的真实公网ip地址怎么样了,看了一些别人的博客后发现,想要获取客户端的公网ip必须借助第三方. packa ...
- Spark MLlib基本算法【相关性分析、卡方检验、总结器】
一.相关性分析 1.简介 计算两个系列数据之间的相关性是统计中的常见操作.在spark.ml中提供了很多算法用来计算两两的相关性.目前支持的相关性算法是Pearson和Spearman.Correla ...
- 【MySQL】备份和恢复
语法 mysqldump -uslave -p -h127.0.0.1 --single-transaction --set-gtid-purged=OFF database1 table1 tabl ...
- 红黑树实现(c/c++)
红黑树 简介 一直想写的一种数据结构,非常厉害的思想,插入,删除,查找,修改,都是\(log_2 n\)的时间复杂度. 比AVL更强大的是,插入删除综合效率比AVL要优秀一点. 性质 一颗红黑树是满足 ...
- Docker搭建Wordpress
搭建 wordpress 1.拉取 wordpress 镜像docker pull wordpress:latest 2.运行 wordpress 镜像 docker run --name wordp ...
- django_restframework项目之数据库搭建(二)
数据库配置 创建数据库 """ 1.管理员连接数据库 2.创建数据库 >: create database luffy default charset=utf8; ...