LockSupport学习
LockSupport工具类定义了一组的公共静态方法,这些方法提供了最基本的线程阻塞和唤醒功能。Java锁和同步器框架的核心工具类AQS:AbstractQueueSynchronizer,就是通过调用LockSupport.park()和LockSupport.unpark()实现线程的阻塞和唤醒。
LockSupport很类似于二元信号量(只有1个许可证可供使用),如果这个许可证还没有被占用,当前线程获取许可并继续执行。如果许可已经被占用,当前线程阻塞,等待获取许可。但是这个许可是不能叠加的,“许可”是一次性的。
比如线程B连续调用了三次unpark函数,当前线程A调用park函数就使用掉这个“许可”,如果线程A再次调用park,则进入等待状态。
注意:unpark函数可以先于park调用。比如线程B调用unpark函数,给线程A发了一个“许可”,那么当线程A调用park时,它发现已经有“许可”了,那么它会马上再继续运行。
park和unpark的灵活之处
上面已经提到了,unpark函数可以先于park调用,这个正是它们的灵活之处。
一个线程它有可能在别的线程unpark之前,或者之后,或者同时调用park,那么因为park的特性,它可以不用担心自己的park的时序问题,否则,如果park必须要在unpark之前,那么给编程带来很大的麻烦!!
考虑一下,两个线程同步,要如何处理?
在Java5里是用wait/notify/notifyAll来同步的。wait和notify机制有个很蛋疼的地方是,比如线程B要用notify通知线程A,那么线程B要确保线程A已经在wait调用上等待了,否则线程A可能永远都在等待。编程的时候就会很蛋疼。
另外,是调用notify,还是notifyALL?
notify只会唤醒一个线程,如果错误地有两个线程在同一个对象上wait等待,那么又悲剧了。为了安全起见,貌似只能调用nofityAll了。
park和unpark模型真正解耦了线程之间的同步,线程之间不再需要一个Objec或者其他变量来存储状态,不再需要关心对方的状态。
LockSupport API的使用
LockSupport提供的阻塞和唤醒方法
| 方法名 | 方法摘要 |
|---|---|
| static void park() | 阻塞当前线程,如果调用了unpark(Thread thread)方法或者当前线程被中断,才能park()方法返回 |
| static void unpark() | 唤醒处于阻塞状态的线程thread |
| static void parkNanos(long nanos) | 阻塞当前线程,最长不超过nanos纳米,返回条件在park()的基础上增加了超时返回 |
| static void parkUntil(long dealine) | 在指定的时限前阻塞当前线程 |
LockSupport 简单使用
public static void main(String[] args) {
Executor executor = Executors.newFixedThreadPool(2);
Thread mainThread = Thread.currentThread() ;
executor.execute(()->{
try {
Thread.sleep(3000L);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("start unpark main thread");
LockSupport.unpark(mainThread);
System.out.println("unpark main thread over");
});
System.out.println("before park");
LockSupport.park();
System.out.println("after park ");
}
运行结果:

先释放许可,再获取许可
@Test
public void test1() {
Thread thread = Thread.currentThread();
LockSupport.unpark(thread);//释放许可
LockSupport.park();// 获取许可
System.out.println("b");
}
中断响应
public static void main(String[] args) {
Executor executor = Executors.newFixedThreadPool(2);
Thread mainThread = Thread.currentThread() ;
executor.execute(()->{
try {
Thread.sleep(3000L);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("start interrupt main thread");
mainThread.interrupt();
System.out.println("interrupt main thread over");
});
System.out.println("before park");
LockSupport.park();
LockSupport.park();
System.out.println("after park ");
}
运行截图:

原理和本文参考
详见:Java的LockSupport.park()实现分析
LockSupport学习的更多相关文章
- Java并发包源码学习之AQS框架(三)LockSupport和interrupt
接着上一篇文章今天我们来介绍下LockSupport和Java中线程的中断(interrupt). 其实除了LockSupport,Java之初就有Object对象的wait和notify方法可以实现 ...
- Java并发包源码学习系列:挂起与唤醒线程LockSupport工具类
目录 LockSupport概述 park与unpark相关方法 中断演示 blocker的作用 测试无blocker 测试带blocker JDK提供的demo 总结 参考阅读 系列传送门: Jav ...
- 多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类)
前言:刚学习了一段机器学习,最近需要重构一个java项目,又赶过来看java.大多是线程代码,没办法,那时候总觉得多线程是个很难的部分很少用到,所以一直没下决定去啃,那些年留下的坑,总是得自己跳进去填 ...
- JAVA并发编程J.U.C学习总结
前言 学习了一段时间J.U.C,打算做个小结,个人感觉总结还是非常重要,要不然总感觉知识点零零散散的. 有错误也欢迎指正,大家共同进步: 另外,转载请注明链接,写篇文章不容易啊,http://www. ...
- JUC.Condition学习笔记[附详细源码解析]
目录 Condition的概念 大体实现流程 I.初始化状态 II.await()操作 III.signal()操作 3个主要方法 Condition的数据结构 线程何时阻塞和释放 await()方法 ...
- JUC.Lock(锁机制)学习笔记[附详细源码解析]
锁机制学习笔记 目录: CAS的意义 锁的一些基本原理 ReentrantLock的相关代码结构 两个重要的状态 I.AQS的state(int类型,32位) II.Node的waitStatus 获 ...
- Java并发包源码学习之AQS框架(四)AbstractQueuedSynchronizer源码分析
经过前面几篇文章的铺垫,今天我们终于要看看AQS的庐山真面目了,建议第一次看AbstractQueuedSynchronizer 类源码的朋友可以先看下我前面几篇文章: <Java并发包源码学习 ...
- Java并发包源码学习之AQS框架(一)概述
AQS其实就是java.util.concurrent.locks.AbstractQueuedSynchronizer这个类. 阅读Java的并发包源码你会发现这个类是整个java.util.con ...
- JUC.Condition学习
JUC.Condition学习笔记[附详细源码解析] 目录 Condition的概念 大体实现流程 I.初始化状态 II.await()操作 III.signal()操作 3个主要方法 Conditi ...
随机推荐
- 【简单算法】37.Shuffle an Array
题目: 打乱一个没有重复元素的数组. 示例: // 以数字集合 1, 2 和 3 初始化数组. ,,}; Solution solution = new Solution(nums); // 打乱数组 ...
- 【逆序对相关/数学】【P1966】【NOIP2013D1T2】 火柴排队
传送门 Description 涵涵有两盒火柴,每盒装有 $n$ 根火柴,每根火柴都有一个高度. 现在将每盒中的火柴各自排成一列, 同一列火柴的高度互不相同, 两列火柴之间的距离定义为:$ \sum ...
- Javascript中的date对象和getTime()方法
有些时候我们需要计算两个日期间的天数,或者小时数等等.下面用JavaScript实现这个需求,然后学习一下需要用到的一些JavaScript函数. JavaScript程序如下: 1 <scri ...
- Centos版本6的使用教程
Centos版本6的使用教程 1.打开VMware workstation 12 PRO 创建新的虚拟机. 2.使用典型类型配置. 3.选择稍后安装操作系统,可以在后面进行安装. 4.选择安装的系统 ...
- Java Zip压缩
1.压缩文件或整个目录 // ZipCompression.java import java.io.File;import java.io.FileInputStream;import java.io ...
- springboot以jar包方式启动、关闭、重启脚本
springboot以jar包方式启动.关闭.重启脚本 启动 编写启动脚本startup.sh #!/bin/bash echo Starting application nohup java -ja ...
- cas 服务端、客服端详细配置
一.准备 1.下载官方源码 CAS-Server下载地址:https://www.apereo.org/projects/cas/download-cas CAS-Client下载地址:http:// ...
- 【Codeforces711E】ZS and The Birthday Paradox [数论]
ZS and The Birthday Paradox Time Limit: 20 Sec Memory Limit: 512 MB Description Input Output Sample ...
- Windows Resizer
Windows ResizerWindows Resizer是chrome浏览器插件,可以调整视口大小
- perl输出重定向
use utf8; open A, ">&STDOUT"; open STDOUT, ">AA.txt"; print STDOUT 'AB ...