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

【并发编程】--- interrupt、interrupted和isInterrupted使用详解

文章目录

  • 1 为何不建议用stop方法中断线程
  • 2 interrupt、interrupted和isInterrupted方法介绍
  • 3 interrupt、interrupted和isInterrupted方法测试
    • 3.1 被中断线程感知到中断请求,但不理会
    • 3.2 isInterrupted方法感知中断请求 --- 仅仅判断当前线程的中断标识
    • 3.3 interrupted方法感知中断请求 --- 该方法被调用后,会将中断标识改回为false
  • 4 实现Runnable接口的方式建立的线程如何安全中断
  • 5 阻塞方法中抛出InterruptedException异常后会将中断标识改回为false ★★★
  • 6 一点注意事项

源码地址:https://github.com/nieandsun/concurrent-study.git

1 为何不建议用stop方法中断线程

在java的世界里,Thread类是对线程概念的抽象。想要中断一个线程有两种方式:

  • (1)调用Thread类的stop方法,
  • (2)组合调用Thread类的 interrupt、interrupted和isInterrupted方法

但是第一种方式是不推荐使用的,并且JDK源码中也已经将其置为了@Deprecated。其原因为使用stop方法进行中断线程本质上是不安全的,它会直接释放掉本线程所持有的所有资源,举个简单的栗子来说,假如我们正在使用某个线程下载电影,如果该线程通过stop进行中断,则原来下载的内容将全部丢失。

正是基于以上原因,JDK提供了、并推荐使用interrupt、interrupted和isInterrupted方法用来进行线程的中断


2 interrupt、interrupted和isInterrupted方法介绍

  • interrupt() 方法 —> 发起线程中断请求,但只是请求,并不会真的把线程给中断,实际上是把线程的中断标识设置为了true;
  • isInterrupted()方法 —> 判断线程的中断标识是否为true
  • interrupted() 方法 —> 判断线程的中断标识是否为true, 方法调用完之后,会将中断标识改为false

总结如下:
在这里插入图片描述


3 interrupt、interrupted和isInterrupted方法测试

测试代码如下:

package com.nrsc.ch1.safeend;/**** 如何安全中断线程 --- 继承Thread类的情况*/
public class EndThread {private static class UseThread extends Thread {public UseThread(String name) {super(name);}@Overridepublic void run() {String threadName = Thread.currentThread().getName();System.err.println(threadName + " interrrupt flag before=" + isInterrupted());//while(true){//while (!isInterrupted()) {while (!Thread.interrupted()) {System.out.println(threadName + " is running");System.out.println(threadName + "inner interrrupt flag ="+ isInterrupted());}System.err.println(threadName + " interrrupt flag after =" + isInterrupted());}}public static void main(String[] args) throws InterruptedException {Thread endThread = new UseThread("endThread");endThread.start();Thread.sleep(1);endThread.interrupt();//中断线程,其实设置线程的标识位true}
}

3.1 被中断线程感知到中断请求,但不理会

即上诉代码的条件为while(true)时

测试结果如下,可以看到endThread 线程已经感知到了中断请求,但是该线程并未终止运行

在这里插入图片描述


3.2 isInterrupted方法感知中断请求 — 仅仅判断当前线程的中断标识

即上诉代码的条件为while (!isInterrupted())时

测试结果如下,可以看到endThread 线程感知到中断线程请求后,由于!isInterrupted() 变为false,将会退出循环,并且退出循环后,当前线程的中断标识仍为true —> 其实这从3.1也可以看出来。

多提一嘴: endThread interrrupt flag after =true这句话之所以会先打印出来,相信大家应该都知道,这是由于idea打印内容到控制台是多线程的,谁先被打印出来,并不完全一定。。。

在这里插入图片描述


3.3 interrupted方法感知中断请求 — 该方法被调用后,会将中断标识改回为false

即上诉代码的条件为while (!Thread.interrupted())时

会有两种结果

  • 结果1, isInterrupted方法先感知到中断请求,如下:

在这里插入图片描述


  • 结果2, isInterrupted方法没感知到中断请求,但interrupted方法率先感知到了:

在这里插入图片描述


但是无论哪种结果,都可以证明:

  • (1)可以使用interrupted方法作为感知线程中断请求的逻辑处理
  • (2)interrupted方法被调用后会将对于该线程的中断请求重新由true改为false

4 实现Runnable接口的方式建立的线程如何安全中断

本文2,3两部分对于线程的管理,采用的是继承Thread类的方式,由于继承自Thread,所以 interrupt、interrupted和isInterrupted可以直接作为内部方法进行调用。

相信大家肯定知道,开启线程还有另外一种方式就是实现Runnable接口,那这种情况下怎样安全的中断线程呢?其实很简单: 只需要通过Thread.currentThread()获取到当前线程就可以了 。这里提供一个简单的栗子:

package com.nrsc.ch1.safeend;/*** 类说明:实现接口Runnable的线程如何中断*/
public class EndRunnable {private static class UseRunnable implements Runnable {@Overridepublic void run() {System.err.println(Thread.currentThread().getName()+ " interrupt flag before ==" + Thread.currentThread().isInterrupted());while (!Thread.currentThread().isInterrupted()) {System.out.println(Thread.currentThread().getName()+ " I am implements Runnable.==" + Thread.currentThread().isInterrupted());}System.err.println(Thread.currentThread().getName()+ " interrupt flag after ==" + Thread.currentThread().isInterrupted());}}public static void main(String[] args) throws InterruptedException {UseRunnable useRunnable = new UseRunnable();Thread endThread = new Thread(useRunnable, "endThread");endThread.start();Thread.sleep(20);endThread.interrupt();}}

5 阻塞方法中抛出InterruptedException异常后会将中断标识改回为false ★★★

比如下面的程序:

package com.nrsc.ch1.safeend;/***类说明:阻塞方法中抛出InterruptedException异常后,如果需要继续中断,需要手动再中断一次*/
public class HasInterrputException {private static class UseThread extends Thread{public UseThread(String name) {super(name);}@Overridepublic void run() {while(!isInterrupted()) {try {Thread.sleep(100);} catch (InterruptedException e) {System.out.println(Thread.currentThread().getName()+" in InterruptedException interrupt flag is "+isInterrupted());//感知到线程中断后,可以先进行资源释放,然后再手动调用一下interrupt()方法进行真正的线程中断//interrupt();e.printStackTrace();}System.out.println(Thread.currentThread().getName()+ " I am extends Thread.");}System.out.println(Thread.currentThread().getName()+" interrupt flag is "+isInterrupted());}}public static void main(String[] args) throws InterruptedException {Thread endThread = new UseThread("HasInterrputEx");endThread.start();Thread.sleep(500);endThread.interrupt();}
}

运行结果如下:

在这里插入图片描述

为什会这样设计呢??? 这里我觉得应该和stop方法被标为@Deprecated的原因一致,就是jdk的设计者,希望你感知到线程中断请求后,可以先做一些其他的事,比如释放资源等,然后再由你自己来决定是不是要中断当前线程。


也就是说如果想让上面的程序停下来,需要打开我代码中那句被注释的代码,打开后的运行效果如下:

在这里插入图片描述


6 一点注意事项

注意: 工作中不要通过自定义变量的方式去中断线程。

http://www.lryc.cn/news/2418157.html

相关文章:

  • 需要了解下Android的Recovery模式
  • 世界上最难的视觉图_世界上最长的蛇有多长?四川惊现55米洪荒巨蟒(图)
  • 各种电子书格式及优缺点
  • 无限制版电驴搜索器(绿色版)
  • 塞尔达传说gba_3分钟快聊《塞尔达传说》全系列
  • 点子库
  • 古文中惊艳的句子,绝对有你想要的!
  • python初学入门————列表
  • 基于51单片机的12864液晶显示4X4矩阵键盘程序仿真
  • q讯家园看加密空间 官方免费版
  • 445port入侵详细解释
  • 如何优化百度搜索引擎?(10个技巧让你的网站更容易被搜索到)
  • MT6732芯片资料MT6732芯片最新参考设计MT6732芯片规格书
  • 验证邮箱平台
  • MEGA是Mega Limited公司推出的一款云存储服务。
  • ProEssentials的MFC 图表库在VS2019-VS2022上机试用教程
  • 计算机丢失lidcef.dll,lidcef.dll(libcef.dll丢失修复文件)V1.0 免费版
  • 浅析近场通信技术特点及未来可能的应用与发展
  • 【备查】DELL服务器硬件报错解决方法——错误代码寄解决和处理办法
  • vb代码大全_VB重点|VB中的各种文件操作方法
  • 常见的15种java开发工具的特点
  • 技能 | 如何申请谷歌地图API密钥
  • vista安装过程
  • _RecordsetPtr异常捕获
  • 详解 c# 克隆
  • 中国版Ubuntu操作系统:“麒麟” ubuntukylin-13.04-desktop
  • java位运算之移位运算
  • 51单片机学习记录-11-LCD1602
  • Linux常用命令及使用方法
  • android移动开发基础案例教程答案,渣本毕业两年经验,文末有彩蛋