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学习的更多相关文章

  1. Java并发包源码学习之AQS框架(三)LockSupport和interrupt

    接着上一篇文章今天我们来介绍下LockSupport和Java中线程的中断(interrupt). 其实除了LockSupport,Java之初就有Object对象的wait和notify方法可以实现 ...

  2. Java并发包源码学习系列:挂起与唤醒线程LockSupport工具类

    目录 LockSupport概述 park与unpark相关方法 中断演示 blocker的作用 测试无blocker 测试带blocker JDK提供的demo 总结 参考阅读 系列传送门: Jav ...

  3. 多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类)

    前言:刚学习了一段机器学习,最近需要重构一个java项目,又赶过来看java.大多是线程代码,没办法,那时候总觉得多线程是个很难的部分很少用到,所以一直没下决定去啃,那些年留下的坑,总是得自己跳进去填 ...

  4. JAVA并发编程J.U.C学习总结

    前言 学习了一段时间J.U.C,打算做个小结,个人感觉总结还是非常重要,要不然总感觉知识点零零散散的. 有错误也欢迎指正,大家共同进步: 另外,转载请注明链接,写篇文章不容易啊,http://www. ...

  5. JUC.Condition学习笔记[附详细源码解析]

    目录 Condition的概念 大体实现流程 I.初始化状态 II.await()操作 III.signal()操作 3个主要方法 Condition的数据结构 线程何时阻塞和释放 await()方法 ...

  6. JUC.Lock(锁机制)学习笔记[附详细源码解析]

    锁机制学习笔记 目录: CAS的意义 锁的一些基本原理 ReentrantLock的相关代码结构 两个重要的状态 I.AQS的state(int类型,32位) II.Node的waitStatus 获 ...

  7. Java并发包源码学习之AQS框架(四)AbstractQueuedSynchronizer源码分析

    经过前面几篇文章的铺垫,今天我们终于要看看AQS的庐山真面目了,建议第一次看AbstractQueuedSynchronizer 类源码的朋友可以先看下我前面几篇文章: <Java并发包源码学习 ...

  8. Java并发包源码学习之AQS框架(一)概述

    AQS其实就是java.util.concurrent.locks.AbstractQueuedSynchronizer这个类. 阅读Java的并发包源码你会发现这个类是整个java.util.con ...

  9. JUC.Condition学习

    JUC.Condition学习笔记[附详细源码解析] 目录 Condition的概念 大体实现流程 I.初始化状态 II.await()操作 III.signal()操作 3个主要方法 Conditi ...

随机推荐

  1. 2016多校联合训练1 D题GCD (ST表+二分)

    暑假颓废了好久啊...重新开始写博客 题目大意:给定10w个数,10w个询问.每次询问一个区间[l,r],求出gcd(a[l],a[l+1],...,a[r])以及有多少个区间[l',r']满足gcd ...

  2. 【贪心】【P2117】小Z的矩阵

    传送门 Description 小Z最近迷上了矩阵,他定义了一个对于一种特殊矩阵的特征函数G.对于N*N的矩阵A,A的所有元素均为0或1, 当然询问一个矩阵的G值实在是太简单了.小Z在给出一个N*N矩 ...

  3. selenium - webdriver - 设置元素等待

    隐式等待:implicitly_wait(value), value默认是0 from selenium import webdriverfrom selenium.common.exceptions ...

  4. hzwer分块九题(暂时持续更新)

    hzwer分块9题 分块1:区间加法,单点查询 Code #include<bits/stdc++.h> #define in(i) (i=read()) using namespace ...

  5. HDU3579 线性同余方程(模板 余数不一定互质)

    Hello Kiki Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Su ...

  6. Qt ------- QMap和QHash的区别

    基本概念: QMap提供了一个从类项为key的键到类项为T的直的映射,通常所存储的数据类型是一个键对应一个值,并且按照Key的次序存储数据.同时这个类也支持一键多值的情况,用类QMultiMap可以实 ...

  7. XSS攻击处理方案

    1. XSS攻击基本概念 XSS是一种经常出现在web应用中的计算机安全漏洞,它允许恶意web用户将代码植入到提供给其它用户使用的页面中.比如这些代码包括HTML代码和客户端脚本.攻击者利用XSS漏洞 ...

  8. Maven-Standard Directory Layout

    顶层工程描述文件: pom.xml. 此外, 还有一些供用户阅读以快速理解工程的文本性文档, 如: readme.txt, license.txt,等. 该结构下只有2个子目录, src和target ...

  9. 【BZOJ4837】LRU算法 [模拟]

    LRU算法 Time Limit: 6 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description 小Q同学在学习操作系统中内存管理的 ...

  10. POJ3495 Bitwise XOR of Arithmetic Progression

    Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 772   Accepted: 175 Description Write ...