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

2024-02-10 11:18

本文主要是介绍【并发编程】- interrupt()、interrupted()、isInterrupted()使用详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 1、为何不建议用stop方法中断线程
  • 2、interrupt、interrupted和isInterrupted方法介绍
  • 3、代码测试
  • 4、总结

源码地址:
https://github.com/suchahaerkang/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、代码测试

package com.wolfx.concurrent.interrupt;/*** @description: 测试用interrupt(),interrupted(),isInterrupted()停止线程* @author: sukang* @date: 2020-04-15 10:41*/
public class Interrupt01 {public static void main(String[] args) {Thread t = new Thread(new Worker());t.start();try {Thread.sleep(5);} catch (InterruptedException e){// TODO Auto-generated catch blocke.printStackTrace();}t.interrupt();System.out.println("Main thread stopped.");}public static class Worker implements Runnable {public void run() {System.out.println("Worker started.");boolean f; //用于检测interrupted()第一次返回值int i = 0;Thread c = Thread.currentThread();System.out.println("while之前线程中断状态isInterrupted():" + c.isInterrupted());while (!(f = Thread.interrupted())) {// 判断是否中断,如果中断,那么跳出并清除中断标志位// 一旦检测到中断,interrupted()第一次返回true,就可以跳出循环,第二次以及以后都是返回falseSystem.out.println("while内,还没中断,interrupted()返回值为:" + f);System.out.println(c.getName() + "  " + i++ + "  " + c.isInterrupted());}System.out.println("跳出循环即第一次中断interrupted()返回值:" + f);System.out.println("while之后线程中断状态isInterrupted():" + c.isInterrupted()); // 为false,因为interrupt()会清除中断标志位,显示为未中断System.out.println("第二次及以后的interrupted()返回值:" + Thread.interrupted());c.interrupt();System.out.println("再次中断后查询中断状态isInterrupted():" + c.isInterrupted());System.out.println("Worker stopped.");}}
}

运行结果:
在这里插入图片描述
…省略一些相同步骤
在这里插入图片描述
分析说明:

1)interrupt()是用于中断线程的,调用该方法的线程的状态将被置为"中断"状态。注意:线程中断仅仅是设置线程的中断状态位,不会停止线程。需要用户自己去监视线程的状态为并做处理。这里可以看到中断后该线程还在继续往下执行,并没有强制终止线程。
2)为什么主线程执行t.interrupt()后再调用isInterrupt()返回false?
因为这里调用interrupted()会清除中断标志位。

还有一种情况:如果线程在wait, sleep,join的时候受阻,调用了interrupt()方法,那么不仅会清除中断标志位,还会抛出InterruptedException异常。
如果线程在wait, sleep,join的时候受阻,调用了interrupt()方法,那么不仅会清除中断标志位,还会抛出 InterruptedException异常。
举个栗子:

package com.wolfx.concurrent.interrupt;/*** @description: 测试如果线程在wait, sleep,join的时候受阻,调用了interrupt()方法,* 那么不仅会清除中断标志位,还会抛出 InterruptedException异常。* @author: sukang* @date: 2020-04-15 10:41*/
public class Interrupt02 {public static void main(String[] args) throws Exception {Thread t = new Thread(new Worker());t.start();Thread.sleep(100);t.interrupt();System.out.println("Main thread stopped.");}public static class Worker implements Runnable {public void run() {System.out.println("Worker started.");try {Thread.sleep(500); // 此时被interrupt()会抛出InterruptedException} catch (InterruptedException e) {Thread thread = Thread.currentThread();System.out.println("再次中断之前isInterrupted():" + thread.isInterrupted());System.out.println("再次中断之前interrupted():" + Thread.interrupted());// 再次调用interrupt方法中断自己,将中断状态设置为“中断”thread.interrupt();System.out.println("再次interrupt()后isInterrupted():" + thread.isInterrupted());System.out.println("再次interrupt()后第一次interrupted()返回:" + Thread.interrupted());// clear status// interrupted()判断是否中断,还会清除中断标志位System.out.println("interrupted()后此时再判断IsInterrupted: " + thread.isInterrupted());System.out.println("---------After Interrupt Status Cleared----------");System.out.println("再次interrupt()后第二次interrupted()返回: " + Thread.interrupted());System.out.println("此时再判断IsInterrupted: " + thread.isInterrupted());}System.out.println("Worker stopped.");}}
}

运行结果
在这里插入图片描述
ps:线程的停止的另外一种方法
除了通过 interrupt 标识为去中断线程以外,我们还可以通过下面这种方式,定义一个 volatile 修饰的成员变量,来控制线程的终止。这实际上是应用了volatile 能够实现多线程之间共享变量的可见性这一特点来实现的。

public class VolatileDemo {private volatile static boolean stop=false;public static void main(String[] args) throws InterruptedException {Thread thread=new Thread(()->{int i=0;while(!stop){i++;}});thread.start();System.out.println("begin start thread");Thread.sleep(1000);stop=true;}
}

4、总结

1)interrupt()方法
如果不会中断sleep,wait,join方法或文档描述的其他情况,就不会抛InterruptException异常,就不会清除中断标志位,isInterrupt()返回true。
如果中断sleep,wait,join等,就会抛InterruptException异常,就会清除中断标志位,isInterrupt()返回false。
2)interrupted()方法
第一次使用返回true,并清除中断标志位,在此之后查询中断状态isInterrupt()都会返回false,刚刚第一个例子也看到了,利用 第一次返回的true可以跳出循环。第二次以及以后都是返回false。
3)isInterrupted()方法
仅仅查询中断标志位来判断是否发生中断并返回true或者false。

这篇关于【并发编程】- interrupt()、interrupted()、isInterrupted()使用详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/696972

相关文章

详解Vue如何使用xlsx库导出Excel文件

《详解Vue如何使用xlsx库导出Excel文件》第三方库xlsx提供了强大的功能来处理Excel文件,它可以简化导出Excel文件这个过程,本文将为大家详细介绍一下它的具体使用,需要的小伙伴可以了解... 目录1. 安装依赖2. 创建vue组件3. 解释代码在Vue.js项目中导出Excel文件,使用第三

SQL注入漏洞扫描之sqlmap详解

《SQL注入漏洞扫描之sqlmap详解》SQLMap是一款自动执行SQL注入的审计工具,支持多种SQL注入技术,包括布尔型盲注、时间型盲注、报错型注入、联合查询注入和堆叠查询注入... 目录what支持类型how---less-1为例1.检测网站是否存在sql注入漏洞的注入点2.列举可用数据库3.列举数据库

Linux之软件包管理器yum详解

《Linux之软件包管理器yum详解》文章介绍了现代类Unix操作系统中软件包管理和包存储库的工作原理,以及如何使用包管理器如yum来安装、更新和卸载软件,文章还介绍了如何配置yum源,更新系统软件包... 目录软件包yumyum语法yum常用命令yum源配置文件介绍更新yum源查看已经安装软件的方法总结软

Linux alias的三种使用场景方式

《Linuxalias的三种使用场景方式》文章介绍了Linux中`alias`命令的三种使用场景:临时别名、用户级别别名和系统级别别名,临时别名仅在当前终端有效,用户级别别名在当前用户下所有终端有效... 目录linux alias三种使用场景一次性适用于当前用户全局生效,所有用户都可调用删除总结Linux

java图像识别工具类(ImageRecognitionUtils)使用实例详解

《java图像识别工具类(ImageRecognitionUtils)使用实例详解》:本文主要介绍如何在Java中使用OpenCV进行图像识别,包括图像加载、预处理、分类、人脸检测和特征提取等步骤... 目录前言1. 图像识别的背景与作用2. 设计目标3. 项目依赖4. 设计与实现 ImageRecogni

Java访问修饰符public、private、protected及默认访问权限详解

《Java访问修饰符public、private、protected及默认访问权限详解》:本文主要介绍Java访问修饰符public、private、protected及默认访问权限的相关资料,每... 目录前言1. public 访问修饰符特点:示例:适用场景:2. private 访问修饰符特点:示例:

python管理工具之conda安装部署及使用详解

《python管理工具之conda安装部署及使用详解》这篇文章详细介绍了如何安装和使用conda来管理Python环境,它涵盖了从安装部署、镜像源配置到具体的conda使用方法,包括创建、激活、安装包... 目录pytpshheraerUhon管理工具:conda部署+使用一、安装部署1、 下载2、 安装3

Mysql虚拟列的使用场景

《Mysql虚拟列的使用场景》MySQL虚拟列是一种在查询时动态生成的特殊列,它不占用存储空间,可以提高查询效率和数据处理便利性,本文给大家介绍Mysql虚拟列的相关知识,感兴趣的朋友一起看看吧... 目录1. 介绍mysql虚拟列1.1 定义和作用1.2 虚拟列与普通列的区别2. MySQL虚拟列的类型2

详解Java如何向http/https接口发出请求

《详解Java如何向http/https接口发出请求》这篇文章主要为大家详细介绍了Java如何实现向http/https接口发出请求,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 用Java发送web请求所用到的包都在java.net下,在具体使用时可以用如下代码,你可以把它封装成一

使用MongoDB进行数据存储的操作流程

《使用MongoDB进行数据存储的操作流程》在现代应用开发中,数据存储是一个至关重要的部分,随着数据量的增大和复杂性的增加,传统的关系型数据库有时难以应对高并发和大数据量的处理需求,MongoDB作为... 目录什么是MongoDB?MongoDB的优势使用MongoDB进行数据存储1. 安装MongoDB