[Java并发]Thread中断机制interrupt

news/2024/9/25 22:11:38

Thread中断机制interrupt

一、中断线程

线程的thread.interrupt()方法是中断线程,将会设置该线程的中断状态位,即设置为true,标记线程处于中断状态,但不会终止线程,线程还会继续执行。中断的结果线程是死亡,还是等待新的任务或是继续运行至下一步,取决于这个程序本身。线程会不时地检测这个中断标示位,以判断是否应该被中断(中断标示值是否为true)。

二、判断线程是否被中断

判断某个线程是否已被发送过中断请求,使用Thread.currentThread().isInterrupted()方法(因为它将线程中断标示位设置为true后,不会立刻清除中断标示位,即不会将中断标示设置为false),不要使用thread.interrupted()(检查当前线程是否已经中断,线程的中断状态由该方法清除,即将中断标示设置为false,如果连续两次调用该方法,则第二次调用将返回false,在第一次调用已清除了其中断状态之后,且第二次调用检验完中断状态前,当前线程再次中断的情况除外)

三、如何中断线程

如果一个线程处于了阻塞状态(如线程调用了thread.sleep、thread.join、thread.wait以及可中断的通道上的IO操作方法后可进入阻塞状态),则线程在检查中断标示时如果发现中断标示为true,则会在这些阻塞方法调用处抛出InterruptedException异常,并且在抛出异常后立即将线程的中断标示位清除,即重新设置为false。抛出异常是为了线程从阻塞状态醒过来,并在结束线程前让程序员有足够的时间来处理中断请求。

中断一个线程只是为了引起该线程的注意,被中断线程可以决定如何应对中断,某些线程非常重要,以至于它们应该不理会中断,而是在处理完抛出的异常之后继续执行,但是普遍的情况是,一个线程将把中断看作一个终止请求。

四、中断应用

1)使用中断信号量中断非阻塞状态的线程

使用共享变量(shared variable)发出信号,告诉线程必须停止正在运行的任务。线程必须周期性的核查这一变量,然后有秩序地中止任务。

public class ThreadExample {public static void main(String[] args) throws  Exception{InterruptThreadBySemaphore interruptThreadBySemaphore = new InterruptThreadBySemaphore();interruptThreadBySemaphore.start();Thread.sleep(3000);System.out.println("asking thread to stop");//设置中断信号量interruptThreadBySemaphore.stop = true;Thread.sleep(3000);System.out.println("stopping application...");}static class InterruptThreadBySemaphore extends Thread {/*** 线程中断信号量*/volatile boolean stop = false;@Overridepublic void run() {super.run();//每隔一秒检测一下中断信号量while (!stop) {System.out.println("thread is running....");long time = System.currentTimeMillis();/*** 使用while循环模拟sleep方法,使用sleep,否则在阻塞时会抛* InterruptedException异常而退出循环*/while ((System.currentTimeMillis() - time) < 1000) {}}System.out.println("thread exiting...");}}
}

2)使用thread.interrupt()中断非阻塞状态线程

public class ThreadExample {public static void main(String[] args) throws  Exception{InterruptThreadByInterrupt interruptThreadByInterrupt = new InterruptThreadByInterrupt();interruptThreadByInterrupt.start();Thread.sleep(3000);System.out.println("asking thread to stop");//发起中断请求interruptThreadByInterrupt.interrupt();Thread.sleep(3000);System.out.println("stopping application...");}static class InterruptThreadByInterrupt extends Thread {@Overridepublic void run() {super.run();//每隔一秒检测一下中断信号量while (!Thread.currentThread().isInterrupted()) {System.out.println("thread is running....");long time = System.currentTimeMillis();/*** 使用while循环模拟sleep方法,使用sleep,否则在阻塞时会抛* InterruptedException异常而退出循环*/while ((System.currentTimeMillis() - time) < 1000) {}}System.out.println("thread exiting...");}}
}

3)使用thread.interrup()中断阻塞状态线程
Thread.interrupt()方法不会中断一个正在运行的线程。是设置线程的中断标示位,在线程受阻塞的地方(如sleep,wait,join等)抛出一个异常InterruptedException,并且中断状态也将被清除,这样线程就得以退出阻塞的状态。

public class ThreadExample {public static void main(String[] args) throws  Exception{InterruptBlockingThread interruptBlockingThread = new InterruptBlockingThread();interruptBlockingThread.start();Thread.sleep(3000);System.out.println("asking thread to stop");interruptBlockingThread.interrupt();Thread.sleep(3000);System.out.println("stopping application...");}static class InterruptBlockingThread extends Thread {@Overridepublic void run() {super.run();while (!Thread.currentThread().isInterrupted()) {System.out.println("thread is running....");try {/*** 如果线程阻塞,将不会去检查中断信号量stop,所以thread.interrupt()* 会使用阻塞线程从阻塞的地方抛出异常,让阻塞线程从阻塞状态逃离出来,* 并进行异常块进行,相应的处理*/Thread.sleep(1000);//线程阻塞,如果线程收到中断操作信号将抛出异常}catch (InterruptedException e){System.out.println("thread interrupted....");/*** 如果线程在调用Object.wait()方法,或者该类的join(),sleep()方法* 过程中受阻,则其中断状态将被清除*/System.out.println(this.isInterrupted());//false/*** 中不中断由自己决定,如果需要中断线程,则重新设置中断位,* 如果不需要,则不用调用*/Thread.currentThread().interrupt();}}System.out.println("thread exiting...");}}
}

五、总结

Java的中断是一种协作机制。也就是说调用线程对象的interrupt()方法并不一定就中断了正在运行的线程,它只是要求线程在合适的时机中断自己。每个线程都有一个boolean的中断状态,interrupt()方法仅仅只是将该状态置为true,比如对正常运行的线程调用interrupt()并不能终止它,只是改变了interrupt标示符。
一般来说,如果一个方法声明抛出InterruptedException,表示该方法是可中断的,比如wait,sleep,join,也就是说可中断方法会对interrupt调用做出响应(例如sleep响应interrupt的操作包括清除中断状态,抛出InterruptedException),异常都是由可中断方法自己抛出来的,并不是直接由interrupt()方法直接引起的。
Object.wait(),Thread.sleep()方法,会不断的轮询监听interrupted标志位,发现其设置为true后,会停止阻塞并抛出InterruptedException异常。

Thread.interrupt() 并不一定会立即中断线程。它只是设置线程的中断状态,实际中断的效果取决于线程的当前状态:

  1. 阻塞状态:如果线程在调用 wait(), sleep(), 或 join()interrupt() 会抛出 InterruptedException,并使线程从阻塞状态恢复。

  2. 运行状态:如果线程正在运行,interrupt() 设置中断标志,但线程需要在代码中主动检查这个标志并处理它,才能响应中断。

  3. 已完成或终止:如果线程已经完成或被终止,interrupt() 不会有任何效果。

因此,正确处理中断状态非常重要,以确保线程能按预期响应中断信号。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/64764.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

9-12

9段好的,我会逐句翻译并解释其中的关键词汇及其发音。 1. **There are, of course, people belonging to all classes who do not want to be fascinated and then enslaved by Admass, and who if necessary are ready to make a few sacrifices, largely material, to achie…

“人民冻凉”简介

账号定位: 这是一个由 复旦大学 的学生运营的 非官方自媒体账号 。 它最大的标签就是 复旦。 其次是复旦附带的的 \(985\)、江浙沪、上海交大、清北华五 这类的 \(\text{tag}\) 。 可以简单理解为,这是一个上海版的 全元光滑 。但实际上,考虑到两者在 学校的地域、创始团队的…

02 深浅拷贝关于 str int bool

深浅拷贝 list /set /dict 一层

河道污染物识别系统

河道污染物识别系统通过深度学习技术,河道污染物识别系统对监控画面中河道污染物以及漂浮物进行全天候实时监测,当河道污染物识别系统监测到河道水面出现污染物时,立即抓拍存档触发告警并同步通知相关人员及时处理。河道污染物识别系统利用河道两旁现场摄像头可及时发现河道…

05 字典内存分配

data_list = [] for i in range(10):data = {}data[user] = idata_list.append(data) print(data_list) #每个字典都 不一样字典,列表内存指向图 data = {} for i in range(10):data[user] = i print(data)内存占用图

00 内存分配 -- 重点

要确认是进行赋值,还是找到其中, 有赋值为:重新开辟内存空间 python 将:-5~ 256为常用的数字(如果在范围类使用同一内存空间,这叫:python小数据池) 如果大于这个数值,会重新 进行开僻内存空间 字符串:如果A1 = ‘’alex A2= ‘alex , A1/A2等于同一个字符串 ,理应不…

01 内存地址 示例

示例一: v1 = [11,22,33] v2 = [11,22,33] v1 = 666 v2 = 666v1 = "asdf" v2 = "asdf"#以上数据都不是同一个内存地址# 按理 v1 和 v2 应该是不同的内存地址。特殊: 1. 整型: -5 ~ 256 2. 字符串:"alex",asfasd asdf asdf d_asdf …