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

相关文章

Android ClassLoader加载机制详解

《AndroidClassLoader加载机制详解》Android的ClassLoader负责加载.dex文件,基于双亲委派模型,支持热修复和插件化,需注意类冲突、内存泄漏和兼容性问题,本文给大家介... 目录一、ClassLoader概述1.1 类加载的基本概念1.2 android与Java Class

Javaee多线程之进程和线程之间的区别和联系(最新整理)

《Javaee多线程之进程和线程之间的区别和联系(最新整理)》进程是资源分配单位,线程是调度执行单位,共享资源更高效,创建线程五种方式:继承Thread、Runnable接口、匿名类、lambda,r... 目录进程和线程进程线程进程和线程的区别创建线程的五种写法继承Thread,重写run实现Runnab

SpringBoot线程池配置使用示例详解

《SpringBoot线程池配置使用示例详解》SpringBoot集成@Async注解,支持线程池参数配置(核心数、队列容量、拒绝策略等)及生命周期管理,结合监控与任务装饰器,提升异步处理效率与系统... 目录一、核心特性二、添加依赖三、参数详解四、配置线程池五、应用实践代码说明拒绝策略(Rejected

Spring事务传播机制最佳实践

《Spring事务传播机制最佳实践》Spring的事务传播机制为我们提供了优雅的解决方案,本文将带您深入理解这一机制,掌握不同场景下的最佳实践,感兴趣的朋友一起看看吧... 目录1. 什么是事务传播行为2. Spring支持的七种事务传播行为2.1 REQUIRED(默认)2.2 SUPPORTS2

Java 线程安全与 volatile与单例模式问题及解决方案

《Java线程安全与volatile与单例模式问题及解决方案》文章主要讲解线程安全问题的五个成因(调度随机、变量修改、非原子操作、内存可见性、指令重排序)及解决方案,强调使用volatile关键字... 目录什么是线程安全线程安全问题的产生与解决方案线程的调度是随机的多个线程对同一个变量进行修改线程的修改操

MySQL中的锁机制详解之全局锁,表级锁,行级锁

《MySQL中的锁机制详解之全局锁,表级锁,行级锁》MySQL锁机制通过全局、表级、行级锁控制并发,保障数据一致性与隔离性,全局锁适用于全库备份,表级锁适合读多写少场景,行级锁(InnoDB)实现高并... 目录一、锁机制基础:从并发问题到锁分类1.1 并发访问的三大问题1.2 锁的核心作用1.3 锁粒度分

Redis的持久化之RDB和AOF机制详解

《Redis的持久化之RDB和AOF机制详解》:本文主要介绍Redis的持久化之RDB和AOF机制,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录概述RDB(Redis Database)核心原理触发方式手动触发自动触发AOF(Append-Only File)核

PostgreSQL中MVCC 机制的实现

《PostgreSQL中MVCC机制的实现》本文主要介绍了PostgreSQL中MVCC机制的实现,通过多版本数据存储、快照隔离和事务ID管理实现高并发读写,具有一定的参考价值,感兴趣的可以了解一下... 目录一 MVCC 基本原理python1.1 MVCC 核心概念1.2 与传统锁机制对比二 Postg

Maven 配置中的 <mirror>绕过 HTTP 阻断机制的方法

《Maven配置中的<mirror>绕过HTTP阻断机制的方法》:本文主要介绍Maven配置中的<mirror>绕过HTTP阻断机制的方法,本文给大家分享问题原因及解决方案,感兴趣的朋友一... 目录一、问题场景:升级 Maven 后构建失败二、解决方案:通过 <mirror> 配置覆盖默认行为1. 配置示

Java中实现线程的创建和启动的方法

《Java中实现线程的创建和启动的方法》在Java中,实现线程的创建和启动是两个不同但紧密相关的概念,理解为什么要启动线程(调用start()方法)而非直接调用run()方法,是掌握多线程编程的关键,... 目录1. 线程的生命周期2. start() vs run() 的本质区别3. 为什么必须通过 st