Java充电社
专辑
博文
联系我
本人继续续收门徒,亲手指导
Java高并发教程
-> 中断线程的几种方式
1、必须知道的几个概念
2、并发级别
3、有关并行的两个重要定律
4、JMM相关的一些概念
5、深入理解进程和线程
6、线程的基本操作
7、volatile与Java内存模型
8、线程组
9、用户线程和守护线程
10、线程安全和synchronized
11、中断线程的几种方式
12、JUC中ReentrantLock
13、JUC中的Condition
14、JUC中的LockSupport工具类
15、UC中的Semaphore(信号量)
16、JUC中的CountDownLatch
17、JUC中的循环栅栏CyclicBarrier
18、线程池
19、JUC中的Executor框架详解1
20、JUC中的Executor框架详解2
21、java中的CAS
22、java中的UnSafe类
23、JUC中的原子操作类
24、ThreadLocal、InheritableThreadLocal
25、JUC中的阻塞队列
26、JUC中一些常见的集合
27、实战:你的接口太慢了需要优化
28、实战:构建日志系统
29、实战:一起来搞懂限流
30、JUC中的CompletableFuture
31、等待线程完成的方式你知道几种?
32、原子操作增强类LongAdder、LongAccumulator
33、怎么演示公平锁和非公平锁
34、谷歌提供的一些好用的并发工具类
35、延迟队列 DelayQueue 详解
36、线程6种状态详解
37、如何实现一个通用的延迟队列?
上一篇:线程安全和synchronized
下一篇:JUC中ReentrantLock
<div style="display:none"></div> ## 目录 [TOC] 本文主要探讨一下中断线程的几种方式。 ## 通过一个变量控制线程中断 代码: ```java package com.itsoku.chat05; import java.util.concurrent.TimeUnit; /** * 微信公众号:路人甲Java,专注于java技术分享(带你玩转 爬虫、分布式事务、异步消息服务、任务调度、分库分表、大数据等),喜欢请关注! */ public class Demo1 { public volatile static boolean exit = false; public static class T extends Thread { @Override public void run() { while (true) { //循环处理业务 if (exit) { break; } } } } public static void setExit() { exit = true; } public static void main(String[] args) throws InterruptedException { T t = new T(); t.start(); TimeUnit.SECONDS.sleep(3); setExit(); } } ``` 代码中启动了一个线程,线程的run方法中有个死循环,内部通过exit变量的值来控制是否退出。`TimeUnit.SECONDS.sleep(3);`让主线程休眠3秒,此处为什么使用TimeUnit?TimeUnit使用更方便一些,能够很清晰的控制休眠时间,底层还是转换为Thread.sleep实现的。程序有个重点:**volatile**关键字,exit变量必须通过这个修饰,如果把这个去掉,程序无法正常退出。volatile控制了变量在多线程中的可见性,关于volatile前面的文章中有介绍,此处就不再说了。 ## 通过线程自带的中断标志控制 示例代码: ```java package com.itsoku.chat05; import java.util.concurrent.TimeUnit; /** * 微信公众号:路人甲Java,专注于java技术分享(带你玩转 爬虫、分布式事务、异步消息服务、任务调度、分库分表、大数据等),喜欢请关注! */ public class Demo2 { public static class T extends Thread { @Override public void run() { while (true) { //循环处理业务 if (this.isInterrupted()) { break; } } } } public static void main(String[] args) throws InterruptedException { T t = new T(); t.start(); TimeUnit.SECONDS.sleep(3); t.interrupt(); } } ``` 运行上面的程序,程序可以正常结束。线程内部有个中断标志,当调用线程的interrupt()实例方法之后,线程的中断标志会被置为true,可以通过线程的实例方法isInterrupted()获取线程的中断标志。 ## 线程阻塞状态中如何中断 示例代码: ```java package com.itsoku.chat05; import java.util.concurrent.TimeUnit; /** * 微信公众号:路人甲Java,专注于java技术分享(带你玩转 爬虫、分布式事务、异步消息服务、任务调度、分库分表、大数据等),喜欢请关注! */ public class Demo3 { public static class T extends Thread { @Override public void run() { while (true) { //循环处理业务 //下面模拟阻塞代码 try { TimeUnit.SECONDS.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } public static void main(String[] args) throws InterruptedException { T t = new T(); t.start(); } } ``` 运行上面代码,发现程序无法结束。 在此先补充几点知识: 1. **调用线程的interrupt()实例方法,线程的中断标志会被置为true** 2. **当线程处于阻塞状态时,调用线程的interrupt()实例方法,线程内部会触发InterruptedException异常,并且会清除线程内部的中断标志(即将中断标志置为false)** 那么上面代码可以调用线程的interrupt()方法来引发InterruptedException异常,来中断sleep方法导致的阻塞,调整一下代码,如下: ```java package com.itsoku.chat05; import java.util.concurrent.TimeUnit; /** * 微信公众号:路人甲Java,专注于java技术分享(带你玩转 爬虫、分布式事务、异步消息服务、任务调度、分库分表、大数据等),喜欢请关注! */ public class Demo3 { public static class T extends Thread { @Override public void run() { while (true) { //循环处理业务 //下面模拟阻塞代码 try { TimeUnit.SECONDS.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); this.interrupt(); } if (this.isInterrupted()) { break; } } } } public static void main(String[] args) throws InterruptedException { T t = new T(); t.start(); TimeUnit.SECONDS.sleep(3); t.interrupt(); } } ``` 运行结果: ```java java.lang.InterruptedException: sleep interrupted at java.lang.Thread.sleep(Native Method) at java.lang.Thread.sleep(Thread.java:340) at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386) at com.itsoku.chat05.Demo3$T.run(Demo3.java:17) ``` 程序可以正常结束了,分析一下上面代码,注意几点: 1. main方法中调用了t.interrupt()方法,此时线程t内部的中断标志会置为true 2. 然后会触发run()方法内部的InterruptedException异常,所以运行结果中有异常输出,上面说了,当触发InterruptedException异常时候,线程内部的中断标志又会被清除(变为false),**所以在catch中又调用了this.interrupt();一次**,将中断标志置为false 3. run()方法中通过this.isInterrupted()来获取线程的中断标志,退出循环(break) ## 总结 1. 当一个线程处于被阻塞状态或者试图执行一个阻塞操作时,可以使用`Thread.interrupt()`方式中断该线程,注意此时将会抛出一个**InterruptedException**的异常,同时中断状态将会被复位(由中断状态改为非中断状态) 2. 内部有循环体,可以通过一个变量来作为一个信号控制线程是否中断,注意变量需要volatile修饰 3. 文中的几种方式可以结合起来灵活使用控制线程的中断 <a style="display:none" target="_blank" href="https://mp.weixin.qq.com/s/_S1DD2JADnXvpexxaBwLLg" style="color:red; font-size:20px; font-weight:bold">继续收门徒,亲手带,月薪 4W 以下的可以来找我</a> ## 最新资料 1. <a href="https://mp.weixin.qq.com/s?__biz=MzkzOTI3Nzc0Mg==&mid=2247484964&idx=2&sn=c81bce2f26015ee0f9632ddc6c67df03&scene=21#wechat_redirect" target="_blank">尚硅谷 Java 学科全套教程(总 207.77GB)</a> 2. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247484192&idx=1&sn=505f2faaa4cc911f553850667749bcbb&scene=21#wechat_redirect" target="_blank">2021 最新版 Java 微服务学习线路图 + 视频</a> 3. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247484573&idx=1&sn=7f3d83892186c16c57bc0b99f03f1ffd&scene=21#wechat_redirect" target="_blank">阿里技术大佬整理的《Spring 学习笔记.pdf》</a> 4. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247484544&idx=2&sn=c1dfe907cfaa5b9ae8e66fc247ccbe84&scene=21#wechat_redirect" target="_blank">阿里大佬的《MySQL 学习笔记高清.pdf》</a> 5. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247485167&idx=1&sn=48d75c8e93e748235a3547f34921dfb7&scene=21#wechat_redirect" target="_blank">2021 版 java 高并发常见面试题汇总.pdf</a> 6. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247485664&idx=1&sn=435f9f515a8f881642820d7790ad20ce&scene=21#wechat_redirect" target="_blank">Idea 快捷键大全.pdf</a> ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/1/2883e86e-3eff-404a-8943-0066e5e2b454.png)
#custom-toc-container