JUC之线程中断机制解读(interrupt)

简介: JUC之线程中断机制解读(interrupt)

首先,一个线程不应该由其他线程来强制中断或停止,而是应该由线程自己自行停止,自己来决定自己的命运。所以,Thread.stop, Thread.suspend, Thread.resume 都已经被废弃了。

其次,在Java中没有办法立即停止一条线程,然而停止线程却显得尤为重要,如取消一个耗时操作。因此,Java提供了一种用于停止线程的协商机制―—中断,也即中断标识协商机制。

可以通过一个标志位来进行线程的中断

1. public class interruptDemo {
2. static volatile boolean isStop = false;
3. 
4. public static void main(String[] args) {
5. new Thread(() -> {
6. while (true) {
7. if (isStop) {
8.                     System.out.println(Thread.currentThread().getName() + "\t isStop被修改为true,程序停止");
9. break;
10.                 }
11.                 System.out.println("t1 is come in ...");
12.             }
13. 
14.         }, "t1").start();
15. try { TimeUnit.MICROSECONDS.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); }
16. new Thread(() -> {
17.             isStop = true;
18.         }, "t2").start();
19. 
20. 
21.     }
22. }

中断只是一种协作协商机制,Java没有给中断增加任何语法,中断的过程完全需要程序员自己实现。若要中断一个线程,你需要手动调用该线程的interrupt方法,该方法也仅仅是将线程对象的中断标识设成true;接着你需要自己写代码不断地检测当前线程的标识位,如果为true,表示别的线程请求这条线程中断,此时究竟该做什么需要你自己写代码实现。

每个线程对象中都有一个中断标识位,用于表示线程是否被中断;该标识位为true表示中断,为false表示未中断;通过调用线程对象的interrupt方法将该线程的标识位设为true;可以在别的线程中调用,也可以在自己的线程中调用。

1. Thread t1 = new Thread(() -> {
2. while (true) {
3. if (Thread.currentThread().isInterrupted()) {
4.                     System.out.println(Thread.currentThread().getName() + "\t isStop被修改为true,程序停止");
5. break;
6.                 }
7.                 System.out.println("t1 is come in ...");
8.             }
9. 
10.         }, "t1");
11.         t1.start();
12. try { TimeUnit.MICROSECONDS.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); }
13.         t1.interrupt();
14.     }

isInterrupted()

1. public boolean isInterrupted() {
2. return isInterrupted(false);
3.     }

测试此线程是否已中断。线程的 中断状态 不受此方法的影响。
由于线程在中断时未处于活动状态而被忽略的线程中断将由此方法反映,返回 false。

isInterrupted(boolean ClearInterrupted)

1. public static boolean interrupted() {
2. return currentThread().isInterrupted(true);
3.     }

测试当前线程是否已中断。此方法将清除线程的 中断状态 。换句话说,如果要连续调用此方法两次,则第二次调用将返回 false(除非在第一个调用清除其中断状态之后,在第二个调用检查它之前,当前线程再次中断)。
由于线程在中断时未处于活动状态而被忽略的线程中断将由此方法反映,返回 false。
返回:true 如果当前线程已中断; false 否则。

interrupt()

1. public void interrupt() {
2. if (this != Thread.currentThread())
3.             checkAccess();
4. 
5. synchronized (blockerLock) {
6. Interruptible b = blocker;
7. if (b != null) {
8.                 interrupt0();           // Just to set the interrupt flag
9.                 b.interrupt(this);
10. return;
11.             }
12.         }
13.         interrupt0();
14.     }

实例方法interrupt()仅仅是设置线程的中断状态为true,发起一个协商而不会立刻停止线程

interrupted()与isInterrupted()的区别

在这里插入图片描述方法的注释也清晰的表达了“中断状态将会根据传入的ClearInterrupted参数值确定是否重置,所以,静态方法interrupted将会清除中断状态(传入的参数ClearInterrupted为true) ,实例方法isInterrupted则不会(传入的参数ClearInterrupted为false)。

不同情况下调用interrupt()

①如果线程处于正常活动状态,那么会将该线程的中断标志设置为 true,仅此而已。被设置中断标志的线程将继续正常运行,不受影响。所以,interrupt()并不能真正的中断线程,需要被调用的线程自己进行配合才行。

②如果线程处于被阻塞状态(例如处于sleep, wait, join等状态),在别的线程中调用当前线程对象的interrupt方法,那么线程将立即退出被阻塞状态,并抛出一个InterruptedException异常。在catch块中应该加上一行代码:Thread.currentThread().interrupt();

如果不加try进行处理,发生异常以后t1线程还在继续跑的

sleep(),wait()方法抛出InterruptException异常后会清除中断标志,即把中断标志设为false。

这时你基本上阻止任何更高级别的方法/线程组注意到中断。这可能会导致问题。通过调用Thread.currentThread().interrupt(),你可以设置线程的中断标志(即把中断标志设为true),因此更高级别的中断处理程序会注意到它并且可以正确处理它。

加了try处理让他再一次进行协商

面试问问

当前线程的中断标识为true,是不是线程就立刻停止?

实例方法interrupt()仅仅是设置线程的中断状态位为true,不会停止线程。中断只是一种协商机制,修改中断标识位仅此而已,不是立刻stop打断

sleep方法抛出InterruptedException后,中断标识也被清空置为false,我们在catch没有通过调用th.interrupt()方法再次将中断标识置为true,这就导致无限循环了


相关文章
|
4月前
|
缓存 安全 Java
JUC系列之《CountDownLatch:同步多线程的精准发令枪 》
CountDownLatch是Java并发编程中用于线程协调的同步工具,通过计数器实现等待机制。主线程等待多个工作线程完成任务后再继续执行,适用于资源初始化、高并发模拟等场景,具有高效、灵活、线程安全的特点,是JUC包中实用的核心组件之一。
|
4月前
|
设计模式 缓存 安全
【JUC】(6)带你了解共享模型之 享元和不可变 模型并初步带你了解并发工具 线程池Pool,文章内还有饥饿问题、设计模式之工作线程的解决于实现
JUC专栏第六篇,本文带你了解两个共享模型:享元和不可变 模型,并初步带你了解并发工具 线程池Pool,文章中还有解决饥饿问题、设计模式之工作线程的实现
270 2
|
4月前
|
Java 测试技术 API
【JUC】(1)带你重新认识进程与线程!!让你深层次了解线程运行的睡眠与打断!!
JUC是什么?你可以说它就是研究Java方面的并发过程。本篇是JUC专栏的第一章!带你了解并行与并发、线程与程序、线程的启动与休眠、打断和等待!全是干货!快快快!
715 2
|
4月前
|
设计模式 消息中间件 安全
【JUC】(3)常见的设计模式概念分析与多把锁使用场景!!理解线程状态转换条件!带你深入JUC!!文章全程笔记干货!!
JUC专栏第三篇,带你继续深入JUC! 本篇文章涵盖内容:保护性暂停、生产者与消费者、Park&unPark、线程转换条件、多把锁情况分析、可重入锁、顺序控制 笔记共享!!文章全程干货!
382 1
|
9月前
|
存储 缓存 安全
JUC并发—11.线程池源码分析
本文主要介绍了线程池的优势和JUC提供的线程池、ThreadPoolExecutor和Excutors创建的线程池、如何设计一个线程池、ThreadPoolExecutor线程池的执行流程、ThreadPoolExecutor的源码分析、如何合理设置线程池参数 + 定制线程池。
JUC并发—11.线程池源码分析
|
并行计算 安全 Java
Python GIL(全局解释器锁)机制对多线程性能影响的深度分析
在Python开发中,GIL(全局解释器锁)一直备受关注。本文基于CPython解释器,探讨GIL的技术本质及其对程序性能的影响。GIL确保同一时刻只有一个线程执行代码,以保护内存管理的安全性,但也限制了多线程并行计算的效率。文章分析了GIL的必要性、局限性,并介绍了多进程、异步编程等替代方案。尽管Python 3.13计划移除GIL,但该特性至少要到2028年才会默认禁用,因此理解GIL仍至关重要。
1080 16
Python GIL(全局解释器锁)机制对多线程性能影响的深度分析
|
存储 监控 安全
深入理解ThreadLocal:线程局部变量的机制与应用
在Java的多线程编程中,`ThreadLocal`变量提供了一种线程安全的解决方案,允许每个线程拥有自己的变量副本,从而避免了线程间的数据竞争。本文将深入探讨`ThreadLocal`的工作原理、使用方法以及在实际开发中的应用场景。
297 2
|
存储 缓存 安全
【Java面试题汇总】多线程、JUC、锁篇(2023版)
线程和进程的区别、CAS的ABA问题、AQS、哪些地方使用了CAS、怎么保证线程安全、线程同步方式、synchronized的用法及原理、Lock、volatile、线程的六个状态、ThreadLocal、线程通信方式、创建方式、两种创建线程池的方法、线程池设置合适的线程数、线程安全的集合?ConcurrentHashMap、JUC
【Java面试题汇总】多线程、JUC、锁篇(2023版)
|
监控 Java 调度
【Java学习】多线程&JUC万字超详解
本文详细介绍了多线程的概念和三种实现方式,还有一些常见的成员方法,CPU的调动方式,多线程的生命周期,还有线程安全问题,锁和死锁的概念,以及等待唤醒机制,阻塞队列,多线程的六种状态,线程池等
1191 6
【Java学习】多线程&JUC万字超详解
|
Java
线程池内部机制:线程的保活与回收策略
【10月更文挑战第24天】 线程池是现代并发编程中管理线程资源的一种高效机制。它不仅能够复用线程,减少创建和销毁线程的开销,还能有效控制并发线程的数量,提高系统资源的利用率。本文将深入探讨线程池中线程的保活和回收机制,帮助你更好地理解和使用线程池。
638 2

热门文章

最新文章