【并发编程】- 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

相关文章

JVisualVM之Java性能监控与调优利器详解

《JVisualVM之Java性能监控与调优利器详解》本文将详细介绍JVisualVM的使用方法,并结合实际案例展示如何利用它进行性能调优,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全... 目录1. JVisualVM简介2. JVisualVM的安装与启动2.1 启动JVisualVM2

MySQL的ALTER TABLE命令的使用解读

《MySQL的ALTERTABLE命令的使用解读》:本文主要介绍MySQL的ALTERTABLE命令的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、查看所建表的编China编程码格式2、修改表的编码格式3、修改列队数据类型4、添加列5、修改列的位置5.1、把列

Python使用FFmpeg实现高效音频格式转换工具

《Python使用FFmpeg实现高效音频格式转换工具》在数字音频处理领域,音频格式转换是一项基础但至关重要的功能,本文主要为大家介绍了Python如何使用FFmpeg实现强大功能的图形化音频转换工具... 目录概述功能详解软件效果展示主界面布局转换过程截图完成提示开发步骤详解1. 环境准备2. 项目功能结

SpringBoot使用ffmpeg实现视频压缩

《SpringBoot使用ffmpeg实现视频压缩》FFmpeg是一个开源的跨平台多媒体处理工具集,用于录制,转换,编辑和流式传输音频和视频,本文将使用ffmpeg实现视频压缩功能,有需要的可以参考... 目录核心功能1.格式转换2.编解码3.音视频处理4.流媒体支持5.滤镜(Filter)安装配置linu

Redis中的Lettuce使用详解

《Redis中的Lettuce使用详解》Lettuce是一个高级的、线程安全的Redis客户端,用于与Redis数据库交互,Lettuce是一个功能强大、使用方便的Redis客户端,适用于各种规模的J... 目录简介特点连接池连接池特点连接池管理连接池优势连接池配置参数监控常用监控工具通过JMX监控通过Pr

apache的commons-pool2原理与使用实践记录

《apache的commons-pool2原理与使用实践记录》ApacheCommonsPool2是一个高效的对象池化框架,通过复用昂贵资源(如数据库连接、线程、网络连接)优化系统性能,这篇文章主... 目录一、核心原理与组件二、使用步骤详解(以数据库连接池为例)三、高级配置与优化四、典型应用场景五、注意事

使用Python实现Windows系统垃圾清理

《使用Python实现Windows系统垃圾清理》Windows自带的磁盘清理工具功能有限,无法深度清理各类垃圾文件,所以本文为大家介绍了如何使用Python+PyQt5开发一个Windows系统垃圾... 目录一、开发背景与工具概述1.1 为什么需要专业清理工具1.2 工具设计理念二、工具核心功能解析2.

MySQL 添加索引5种方式示例详解(实用sql代码)

《MySQL添加索引5种方式示例详解(实用sql代码)》在MySQL数据库中添加索引可以帮助提高查询性能,尤其是在数据量大的表中,下面给大家分享MySQL添加索引5种方式示例详解(实用sql代码),... 在mysql数据库中添加索引可以帮助提高查询性能,尤其是在数据量大的表中。索引可以在创建表时定义,也可

Linux系统之stress-ng测压工具的使用

《Linux系统之stress-ng测压工具的使用》:本文主要介绍Linux系统之stress-ng测压工具的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、理论1.stress工具简介与安装2.语法及参数3.具体安装二、实验1.运行8 cpu, 4 fo

C++ RabbitMq消息队列组件详解

《C++RabbitMq消息队列组件详解》:本文主要介绍C++RabbitMq消息队列组件的相关知识,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1. RabbitMq介绍2. 安装RabbitMQ3. 安装 RabbitMQ 的 C++客户端库4. A