JUC-线程中断机制和LockSupport

2024-01-16 02:44

本文主要是介绍JUC-线程中断机制和LockSupport,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

线程中断机制

概念

java提供了一种用于停止线程的协商机制-中断。称为中断标识协商机制。

常用API

  • public void interrupt()
    仅仅让线程的中断标志位设置为true。不进行其他操作。
  • public boolean isInterrupted()
    获取中断标志位的状态。
  • public static boolean interrupted()
    获取中断标志位的状态。并将中断标志位设置为false

如何停止中断运行的线程

volatile变量实现

private static volatile boolean isStop = false;public static void main(String[] args) {new Thread(() -> {while (true) {if (isStop) {System.out.println(Thread.currentThread().getName() + "线程isStop = true,自己退出");break;}System.out.println("-------hello interrupt--------");}}, "t1").start();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}isStop = true;}

AtomicBoolean实现

private static final AtomicBoolean atomicBoolean = new AtomicBoolean(true);public static void main(String[] args) {new Thread(() -> {while (atomicBoolean.get()) {try {TimeUnit.MILLISECONDS.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("-------hello------");}}).start();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}atomicBoolean.set(false);}

中断API interrupt和isInterrupted

public static void main(String[] args) {Thread t1 = new Thread(() -> {while (true) {if (Thread.currentThread().isInterrupted()) {System.out.println("-----t1 线程被中断了,程序结束");break;}System.out.println("-----hello-------");}}, "t1");t1.start();System.out.println("t1是否被中断:" + t1.isInterrupted());try {TimeUnit.MILLISECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}t1.interrupt();System.out.println("t1是否被中断:" + t1.isInterrupted());}

注意

  • 如果线程处于正常活动状态,interrupt会将该线程中断状态位设置为true。要想该线程进行进一步处理需要自己根据中断状态为来写业务逻辑。
  • 如果线程处于阻塞状态(sleep, wait, join)在别的线程调用当前线程interrupt方法,那么线程立即退出阻塞状态,并抛出InterruptException异常,并将中断标志为清除(置为false)
Thread t1 = new Thread(() -> {while (true){if(Thread.currentThread().isInterrupted()){System.out.println(Thread.currentThread().getName()+"\t " +"中断标志位:"+Thread.currentThread().isInterrupted()+" 程序停止");break;}try {Thread.sleep(200);} catch (InterruptedException e) {Thread.currentThread().interrupt();//为什么要在异常处,再调用一次??// 阻塞状态下的线程设置中断标志位为true,会报异常。中断状态位置为false。导致死循环。因此需要再次设置为truee.printStackTrace();}System.out.println("-----hello InterruptDemo3");}}, "t1");t1.start();//暂停几秒钟线程try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }new Thread(() -> t1.interrupt(),"t2").start();

拓展:线程有哪些状态?7种状态
创建,就绪(等待CPU),运行,阻塞(等待锁对象),等待(等待事件),超时等待,结束
sleep不会释放锁。wait会释放锁。因此sleep进入等待状态。wait进入阻塞状态。

LockSupport

LockSupport是线程阻塞和唤醒的工具类。主要通过park阻塞和unpark唤醒。

线程等待唤醒机制

Synchronized锁对象的wait和notify

Object objectLock = new Object();new Thread(() -> {try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }synchronized (objectLock){System.out.println(Thread.currentThread().getName()+"\t ----come in");try {objectLock.wait();} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"\t ----被唤醒");}},"t1").start();//暂停几秒钟线程//try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }new Thread(() -> {synchronized (objectLock){objectLock.notify();System.out.println(Thread.currentThread().getName()+"\t ----发出通知");}},"t2").start();

限制:

  • 必须在Synchronized同步块中
  • wait必须在之前notify。否则通知唤醒会失效。

Lock.condition的await和signal

 Lock lock = new ReentrantLock();Condition condition = lock.newCondition();new Thread(() -> {try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }lock.lock();try{System.out.println(Thread.currentThread().getName()+"\t ----come in");condition.await();System.out.println(Thread.currentThread().getName()+"\t ----被唤醒");} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}},"t1").start();//暂停几秒钟线程//try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }new Thread(() -> {lock.lock();try{condition.signal();System.out.println(Thread.currentThread().getName()+"\t ----发出通知");}finally {lock.unlock();}},"t2").start();

LockSupport的park和unpark

Thread t1 = new Thread(() -> {try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }System.out.println(Thread.currentThread().getName() + "\t ----come in"+System.currentTimeMillis());LockSupport.park();System.out.println(Thread.currentThread().getName() + "\t ----被唤醒"+System.currentTimeMillis());}, "t1");t1.start();//暂停几秒钟线程//try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }new Thread(() -> {LockSupport.unpark(t1);System.out.println(Thread.currentThread().getName()+"\t ----发出通知");},"t2").start();

优点:

  • 不需要在锁块中,本身就可以让线程同步。
  • park和unpark不需要有先后顺序。unpark相当于给了park一个凭证。unpark在park执行前也可以让park唤醒。相当于提前给了凭证。(而前面两种就不行)
  • 一个park需要一个凭证。但是不同的unpark作用于一个线程只能给一个凭证。(即是连续调用多次unpark和调用一次作用是一样的)

这篇关于JUC-线程中断机制和LockSupport的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/611068

相关文章

Java中如何正确的停掉线程

《Java中如何正确的停掉线程》Java通过interrupt()通知线程停止而非强制,确保线程自主处理中断,避免数据损坏,线程池的shutdown()等待任务完成,shutdownNow()强制中断... 目录为什么不强制停止为什么 Java 不提供强制停止线程的能力呢?如何用interrupt停止线程s

基于Redis自动过期的流处理暂停机制

《基于Redis自动过期的流处理暂停机制》基于Redis自动过期的流处理暂停机制是一种高效、可靠且易于实现的解决方案,防止延时过大的数据影响实时处理自动恢复处理,以避免积压的数据影响实时性,下面就来详... 目录核心思路代码实现1. 初始化Redis连接和键前缀2. 接收数据时检查暂停状态3. 检测到延时过

python 线程池顺序执行的方法实现

《python线程池顺序执行的方法实现》在Python中,线程池默认是并发执行任务的,但若需要实现任务的顺序执行,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋... 目录方案一:强制单线程(伪顺序执行)方案二:按提交顺序获取结果方案三:任务间依赖控制方案四:队列顺序消

Redis中哨兵机制和集群的区别及说明

《Redis中哨兵机制和集群的区别及说明》Redis哨兵通过主从复制实现高可用,适用于中小规模数据;集群采用分布式分片,支持动态扩展,适合大规模数据,哨兵管理简单但扩展性弱,集群性能更强但架构复杂,根... 目录一、架构设计与节点角色1. 哨兵机制(Sentinel)2. 集群(Cluster)二、数据分片

深入理解go中interface机制

《深入理解go中interface机制》本文主要介绍了深入理解go中interface机制,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录前言interface使用类型判断总结前言go的interface是一组method的集合,不

SpringBoot实现虚拟线程的方案

《SpringBoot实现虚拟线程的方案》Java19引入虚拟线程,本文就来介绍一下SpringBoot实现虚拟线程的方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录什么是虚拟线程虚拟线程和普通线程的区别SpringBoot使用虚拟线程配置@Async性能对比H

C# async await 异步编程实现机制详解

《C#asyncawait异步编程实现机制详解》async/await是C#5.0引入的语法糖,它基于**状态机(StateMachine)**模式实现,将异步方法转换为编译器生成的状态机类,本... 目录一、async/await 异步编程实现机制1.1 核心概念1.2 编译器转换过程1.3 关键组件解析

Nginx进行平滑升级的实战指南(不中断服务版本更新)

《Nginx进行平滑升级的实战指南(不中断服务版本更新)》Nginx的平滑升级(也称为热升级)是一种在不停止服务的情况下更新Nginx版本或添加模块的方法,这种升级方式确保了服务的高可用性,避免了因升... 目录一.下载并编译新版Nginx1.下载解压2.编译二.替换可执行文件,并平滑升级1.替换可执行文件

在Java中实现线程之间的数据共享的几种方式总结

《在Java中实现线程之间的数据共享的几种方式总结》在Java中实现线程间数据共享是并发编程的核心需求,但需要谨慎处理同步问题以避免竞态条件,本文通过代码示例给大家介绍了几种主要实现方式及其最佳实践,... 目录1. 共享变量与同步机制2. 轻量级通信机制3. 线程安全容器4. 线程局部变量(ThreadL

Linux线程同步/互斥过程详解

《Linux线程同步/互斥过程详解》文章讲解多线程并发访问导致竞态条件,需通过互斥锁、原子操作和条件变量实现线程安全与同步,分析死锁条件及避免方法,并介绍RAII封装技术提升资源管理效率... 目录01. 资源共享问题1.1 多线程并发访问1.2 临界区与临界资源1.3 锁的引入02. 多线程案例2.1 为