Java JUC LockSupport 概述

简介: LockSupport 工具类

LockSupport 工具类


LockSupport 是 rt.jar 包中的一个工具类,它的主要作用就是挂起唤醒线程,并且该类是创建锁和其它同步类的基础


LockSupport 类和每个使用它的线程都会关联一个许可证,在默认情况下调用 LockSupport 类的方法是不持有许可证的。LockSupport 是使用 Unsafe 类实现的。


下面介绍一下 LockSupport 中的主要方法。


void park()

如果在调用 park()方法之前已经获得到关联的许可证,则调用后会立即返回,否则会被禁止参与线程的调度,也就是被阻塞挂起。


如下代码,最终只会输出“开始”,然后当前线程被挂起,因为在默认情况下调用线程是不持有许可证的。

public static void main(String[] args) throws Exception {
        System.out.println("开始...");
        LockSupport.park();
        System.out.println("结束...");
}
//结果:
//开始...

在其它线程调用 unpark(Thread thread)方法并且将当前阻塞线程作为参数时,调用 park()方法阻塞的线程会被返回。当其它线程调用了阻塞线程的 interrupt()方法,设置中断标志或者线程被虚假唤醒,则阻塞线程也会被返回。


需要注意:

  1. 当调用 park()方法被阻塞的线程被其它线程中断而返回时候,并不会抛出 InterruptedException 异常。
  2. 许可证是一次性的。比如线程 B 连续调用了三次 unpark()方法,当线程 A 调用 park()方法就使用掉这个许可证,如果线程 A 再次调用 park()方法,则进入等待状态。


void unpark(Thread t)

当一个线程调用 unpark()方法时,如果传入的参数 thread 没有持有许可证,则让传入的 thread 持有许可证;如果 thread 之前调用 park()后被挂起,则调用 unpark()时会唤醒该 thread;如果 thread 之前没有调用 park(),则调用 unpark()方法后,再调用 park()方法时会立即返回。

public static void main(String[] args) throws Exception {
        System.out.println("开始...");
        LockSupport.unpark(Thread.currentThread());
        LockSupport.park();
        System.out.println("结束...");
}
//输出结果:
//开始...
//结束...

看如下代码,加深对 park 和 unpark 的理解。

public static void main(String[] args) throws Exception {
        Thread t = new Thread(() -> {
            System.out.println("子线程开始...");
            //挂起自己
            LockSupport.park();
            System.out.println("子线程结束...");
        });
        t.start();
        Thread.sleep(1000);
        System.out.println("主线程开始调用unpark");
        LockSupport.unpark(t);
}
//输出结果:
//子线程开始...
//主线程开始调用unpark
//子线程结束...

该段代码首先创建了子线程 t,子线程启动后调用 park()方法。由于默认情况下子线程没有持有许可证,则挂起自己。


主线程休眠 1 秒后,调用 unpark()并传入子线程 t,这样做就是为了让子线程获取到许可证,之后子线程中阻塞的 park()就会返回。


void parkNanos(long nanos)

和 park()方法类似,如果已经获取到了许可证则调用该方法后会马上返回。不同的是,如果没有拿到许可证,则调用线程会被挂起 nanos 时间后自动返回。


另外 park()方法还支持带有 blocker 参数的方法 void park(Object blocker)方法,当线程在没有持有许可证的情况下调用 park()方法而被阻塞挂起时,这个 blocker 对象会被记录到该线程内部。一般用于用于标识阻塞对象,该对象主要用于问题排查和系统监控


void parkNanos(Object blocker,long nanos) 该方法相对于上个方法,增加了超时时间。


void parkUntil(Object blocker,long deadline)

public static void parkUntil(Object blocker, long deadline) {
        Thread t = Thread.currentThread();
        setBlocker(t, blocker);
        UNSAFE.park(true, deadline);
        setBlocker(t, null);
}

参数 deadline 的时间单位为 ms,这个方法和 parkNanos(Object blocker,long nanos)的区别是,后者是从当前时间等待 nanos 秒时间,而前者是指定一个时间点,比如 2022-01-19 12:00:00。


总结

与 Object 类的 wait/notify 机制相比,park/unpark 有两个优点:


  • 以 thread 为操作对象更符合阻塞线程的直观定义
  • 操作更精准,可以准确地唤醒某一个线程(notify 随机唤醒一个线程,notifyAll 唤醒所有等待的线程),增加了灵活性
相关文章
|
3月前
|
安全 Java API
JAVA并发编程JUC包之CAS原理
在JDK 1.5之后,Java API引入了`java.util.concurrent`包(简称JUC包),提供了多种并发工具类,如原子类`AtomicXX`、线程池`Executors`、信号量`Semaphore`、阻塞队列等。这些工具类简化了并发编程的复杂度。原子类`Atomic`尤其重要,它提供了线程安全的变量更新方法,支持整型、长整型、布尔型、数组及对象属性的原子修改。结合`volatile`关键字,可以实现多线程环境下共享变量的安全修改。
|
2月前
|
存储 消息中间件 安全
JUC组件实战:实现RRPC(Java与硬件通过MQTT的同步通信)
【10月更文挑战第9天】本文介绍了如何利用JUC组件实现Java服务与硬件通过MQTT的同步通信(RRPC)。通过模拟MQTT通信流程,使用`LinkedBlockingQueue`作为消息队列,详细讲解了消息发送、接收及响应的同步处理机制,包括任务超时处理和内存泄漏的预防措施。文中还提供了具体的类设计和方法实现,帮助理解同步通信的内部工作原理。
JUC组件实战:实现RRPC(Java与硬件通过MQTT的同步通信)
|
3月前
|
存储 缓存 安全
【Java面试题汇总】多线程、JUC、锁篇(2023版)
线程和进程的区别、CAS的ABA问题、AQS、哪些地方使用了CAS、怎么保证线程安全、线程同步方式、synchronized的用法及原理、Lock、volatile、线程的六个状态、ThreadLocal、线程通信方式、创建方式、两种创建线程池的方法、线程池设置合适的线程数、线程安全的集合?ConcurrentHashMap、JUC
【Java面试题汇总】多线程、JUC、锁篇(2023版)
|
3月前
|
监控 Java 调度
【Java学习】多线程&JUC万字超详解
本文详细介绍了多线程的概念和三种实现方式,还有一些常见的成员方法,CPU的调动方式,多线程的生命周期,还有线程安全问题,锁和死锁的概念,以及等待唤醒机制,阻塞队列,多线程的六种状态,线程池等
184 6
【Java学习】多线程&JUC万字超详解
|
3月前
|
安全 Java API
Java 18 概述:新特性一览
Java 18 作为 Java 平台的最新版本,引入了多项令人振奋的新特性和改进,包括模式匹配、记录类型、流库改进、外部函数与内存 API 以及并发处理增强。这些新功能不仅提升了开发者的生产力,还显著增强了 Java 的性能和安全性。本文将详细介绍 Java 18 的主要新特性,并通过代码示例帮助读者更好地理解和应用这些功能。
|
4月前
|
存储 Oracle Java
01 Java概述基础与计算机基础(DOS+进制+原码反码补码)
01 Java概述基础与计算机基础(DOS+进制+原码反码补码)
46 17
|
4月前
|
存储 算法 Oracle
19 Java8概述(Java8概述+lambda表达式+函数式接口+方法引用+Stream+新时间API)
19 Java8概述(Java8概述+lambda表达式+函数式接口+方法引用+Stream+新时间API)
70 8
|
4月前
|
Java 数据安全/隐私保护
09 Java面向对象三大特征(概述)
09 Java面向对象三大特征(概述)
73 4
|
6月前
|
存储 缓存 Java
深入剖析Java并发库(JUC)之StampedLock的应用与原理
深入剖析Java并发库(JUC)之StampedLock的应用与原理
深入剖析Java并发库(JUC)之StampedLock的应用与原理
|
6月前
|
安全 Java
深入探索Java并发库(JUC)中的ReentrantReadWriteLock
深入探索Java并发库(JUC)中的ReentrantReadWriteLock