首先,一个线程不应该由其他线程来强制中断或停止,而是应该由线程自己自行停止。

所以,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()到底意味着什么的更多相关文章

  1. Java并发专题(一)认识线程

    1.1 认识线程 线程是轻量级进程,也是程序执行的一个路径,每一个线程都有自己的局部变量表.程序计数器(指向正在执行的指令指针)以及各自的生命周期,现代操作系统中一般不止一个线程在运行.比如说,当我们 ...

  2. java并发编程(五)----(JUC)ReentrantLock

    上一节我们了解了Lock接口的一些简单的说明,知道Lock锁的常用形式,那么这节我们正式开始进入JUC锁(java.util.concurrent包下的锁,简称JUC锁).下面我们来看一下Lock最常 ...

  3. 关于InterruptedException的两篇博文的转载

    博文一:https://www.jianshu.com/p/a8abe097d4ed InterruptedException异常 在了解InterruptedException异常之前应该了解以下的 ...

  4. HackerNews——《Pokemon Go玩家存在巨大的安全风险》

    译者注:原文来自HackerNews,首发tumblr,标题为Pokemon Go is a huge security risk.作者Adam Reeve,附一张这个胖子的帅照   (正文)之所以会 ...

  5. 如何设计一门语言(七)——闭包、lambda和interface

    人们都很喜欢讨论闭包这个概念.其实这个概念对于写代码来讲一点用都没有,写代码只需要掌握好lambda表达式和class+interface的语义就行了.基本上只有在写编译器和虚拟机的时候才需要管什么是 ...

  6. 【转】漫谈iOS程序的证书和签名机制

    转自:漫谈iOS程序的证书和签名机制 接触iOS开发半年,曾经也被这个主题坑的摸不着头脑,也在淘宝上买过企业证书签名这些服务,有大神都做了一个全自动的发布打包(不过此大神现在不卖企业证书了),甚是羡慕 ...

  7. Java线程并发:知识点

    Java线程并发:知识点   发布:一个对象是使它能够被当前范围之外的代码所引用: 常见形式:将对象的的引用存储到公共静态域:非私有方法中返回引用:发布内部类实例,包含引用.   逃逸:在对象尚未准备 ...

  8. 漫谈iOS程序的证书和签名机制

    接触iOS开发半年,曾经也被这个主题坑的摸不着头脑,也在淘宝上买过企业证书签名这些服务,有大神都做了一个全自动的发布打包(不过此大神现在不卖企业证书了),甚是羡慕和崇拜.于是,花了一点时间去研究了一下 ...

  9. Guava学习笔记(1):Optional优雅的使用null

    转自:http://www.cnblogs.com/peida/archive/2013/06/14/Guava_Optional.html 参考:[Google Guava] 1.1-使用和避免nu ...

随机推荐

  1. 微服务架构 ------ Ubuntu下Docker的安装

    1.准备一个全新的Ubuntu环境 2.准备安装Docker及其依赖 apt-get update 更新数据源 apt-get -y install apt-transport-https ca-ce ...

  2. ES6兼容ie9, flex兼容ie9

    vue兼容ES6 在 ie9 的环境上,es6 的部分新对象.表达式,并不支持,解决方案是使用 babel-polyfill 组件,它可以将 es6 的代码翻译成低版本浏览器可以识别的 es5 代码 ...

  3. Django的视图系统:View

    一.CBV和FBV FBV:functoin based view,基于函数的view 我们之前写过的都是基于函数的view CBV:class based view,基于类的view 定义CBV: ...

  4. 转摘python3.4 + pycharm 环境安装 + pycharm使用

    遇到很多初学者的盆友,来问python环境安装的问题..因此,这篇文章就诞生了.. 因个人是windows的环境,所以本文只讲windows环境下的python安装. 作为初用python的盆友,强烈 ...

  5. nginx.conf 下日志host.access.log 说明

    位置usr/local/nginx/conf/nginx.conf $server_port 请求端口 $remote_addr 局域网代理IP:如果没同意任何代理的话$remote_addr 就是真 ...

  6. 《Pro Continuous Delivery With Jenkins 2.0》随书笔记

    今天同时看完<Pro Continuous Delivery With Jenkins 2.0>, 这书与工作关系很大,但也是快速翻翻. 本书着重点jenkins高可用环境搭建,与gith ...

  7. Centos7离线部署docker

    下载docker离线包 wget https://download.docker.com/linux/static/stable/x86_64/docker-19.03.5.tgz 解压 tar -x ...

  8. 重新学习Spring注解——AOP

    面向切面编程——思想:在一个地方定义通用功能,但是可以通过声明的方式定义这个功能要以何种方式在何处运用,而无须修改受影响的类. 切面:横切关注点可以被模块化为特殊的类. 优点: 1.每个关注点都集中在 ...

  9. 模板语言、url

    伪造一个数据库全局变量 (字典无序) USER_LIST 列表变字典(元祖和列表直接循环就好,字典涉及到k_v) UESR_DICT 遍历方法 1. 2. 3. 4. 5. 6.键入链接 通过a标签包 ...

  10. VIJOS-P1294 拯救OIBH总部

    洛谷 P1506 拯救oibh总部 洛谷传送门 JDOJ:1405: VIJOS-P1294 拯救OIBH总部 JDOJ传送门 Description OIBH被突来的洪水淹没了> .< ...