Thread 之 interrupt、isInterrupted、interrupted 方法
interrupt(): 打断 sleep、wait、join 的线程会抛出 InterruptedException 异常并清除打断标记,如果打断正在运行的线程、park 的线程则会重新设置打断标记
isInterrupted(): 不会清除打断标记
interrupted(): 会清除打断标记
一、调用 interrupt() 方法中断正在运行的线程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | @Slf4j public class InterruptDemo { public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(() -> { while ( true ) { } }); t1.start(); // 先让 t1 线程运行 TimeUnit.SECONDS.sleep( 1 ); // isInterrupted() 可以获取到线程的打断标记,如果线程被打断,则打断标记为 true,并且该方法不会清除打断标记 log.info( "before interrupt status >>> {}" , t1.isInterrupted()); // 打断正在运行的线程/park 状态的线程会重新设置打断标记,打断 sleep、join、wait 状态的线程会抛出 InterruptedException 异常,并且会清除打断标记 t1.interrupt(); log.info( "after interrupt status >>> {}" , t1.isInterrupted()); } } |
中断正在运行的线程时,线程的中断状态变成 true,线程正常运行,并不会停止下来
调用 interrupt() 方法中断处于 sleep、wait、join 状态的线程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | @Slf4j public class InterruptDemo { public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(() -> { try { // t1 线程休眠 1000s TimeUnit.SECONDS.sleep( 1000 ); } catch (InterruptedException e) { e.printStackTrace(); log.info( "{} 线程被打断了" , Thread.currentThread().getName()); } }, "t1" ); t1.start(); // 主线程休眠 2s,让 t1 线程有足够的时间进入 sleep 状态 TimeUnit.SECONDS.sleep( 2 ); log.info( "before interrupt status >>> {}" , t1.isInterrupted()); t1.interrupt(); // 主线程休眠 2s,让 t1 线程有足够的时间进行 interrupt 操作 TimeUnit.SECONDS.sleep( 2 ); log.info( "after interrupt status >>> {}" , t1.isInterrupted()); } } |
中断处于 sleep、join、wait 状态的线程会抛出异常,并且会将中断状态重置为 false
中断时线程的状态 | 中断后线程的中断标记 | 中断后线程运行情况 |
正常运行的线程 | false -> true | 线程正常运行 |
sleep、wait、join 状态的线程 | false -> true -> false | 线程抛出异常,中止运行 |
然后再看一下 isInterrupted 和 interrupted 的区别
先看一下 isInterrupted() 方法源码
1 2 3 4 5 6 7 | public boolean isInterrupted() { // ClearInterrupted 参数的含义是否清除打断标记 // false 代表不清除,打断之后 false -> true // true 代表清除,打断之后会重置打断标记 false -> true -> false return isInterrupted( false ); } private native boolean isInterrupted( boolean ClearInterrupted); |
接着再看一下 interrupted() 方法源码
1 2 3 4 | public static boolean interrupted() { return currentThread().isInterrupted( true ); } private native boolean isInterrupted( boolean ClearInterrupted); |
从上面的源码中可以看出 isInterrupted() 方法和 interrupted() 方法实际上底层都是调用 private native boolean isInterrupted(boolean ClearInterrupted) 方法,唯一的区别就是传递的参数,一个是 false,一个是 true,也就是一个不会清除打断标记,另外一个会清除打断标记
线程调用 interrupt() 方法并不会真正中断线程,而是让线程具有响应中断的能力,如果你可以在 main 线程中随意的去停止 t1 线程,而 t1 线程却毫无察觉,这不是一件很可怕的事情吗,真正中断的操作应该由 t1 线程去决定,而不是 main 线程,常用的做法是在 t1 线程中根据打断标记去执行不同的逻辑
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?