并发编程(五)LockSupport

LockSupport 提供 park() 和 unpark() 方法实现阻塞线程和解除线程阻塞,实现的阻塞和解除阻塞是基于“许可(permit)”作为关联,permit 相当于一个信号量(0,1),默认是0。 线程之间不再需要一个 Object 或者其它变量来存储状态,不再需要关心对方的状态。

一、LockSupport API

(1) pack

方法 说明
park() 挂起当前线程
park(Object blocker) 挂起当前线程
parkNanos(long nanos) 指定挂起时间(相对于当前的时间),时间到后自动被唤醒
parkNanos(Object blocker, long nanos) 指定挂起时间(相对于当前的时间)
parkUntil(long deadline) 指定挂起时间(绝对时间),时间到后自动被唤醒
parkUntil(Object blocker, long deadline) 指定挂起时间(绝对时间),时间到后自动被唤醒

从上面表格可以看出,park 支持 blocker 对象作为参数,该字段是 Thread 类,专门为 LockSupport 而设计的。此 blocker 对象在线程受阻塞时被记录,这样监视工具和诊断工具就可以确定线程受阻塞的原因。建议最好使用这些带 blocker 的方法版本,而不是不带 blocker 参数的方法。

public static void park() {
UNSAFE.park(false, 0L);
}

(2) unpark

设置线程许可为可用。

  • 如果线程当前已经被 pack 挂起,那么这个线程将会被唤醒。
  • 如果线程当前没有被挂起,那么下次调用 pack 不会挂起线程。
public static void unpark(Thread thread) {
if (thread != null)
UNSAFE.unpark(thread);
}

二、LockSupport 使用

(1) 先park后unpark

public void test1() throws Exception {
Thread mainThread = Thread.currentThread();
Thread thread = new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("before unpark, " + LockSupport.getBlocker(mainThread));
LockSupport.unpark(mainThread);
System.out.println("after unpark, " + LockSupport.getBlocker(mainThread));
});
thread.start();
System.out.println("before park");
// 等待获取许可
LockSupport.park("Park");
System.out.println("after park");
}

结果:

before park
before unpark, Park
after park
after unpark, null

(2) 先unpark后unpark

先执行 unpark,在调用 park,直接就没被阻塞, 因此 park/unpark 相比 wait/notify 更加的灵活

public void test2() throws Exception {
Thread mainThread = Thread.currentThread();
Thread thread = new Thread(() -> {
System.out.println("before unpark, " + LockSupport.getBlocker(mainThread));
LockSupport.unpark(mainThread);
System.out.println("after unpark, " + LockSupport.getBlocker(mainThread));
});
thread.start(); TimeUnit.SECONDS.sleep(1);
System.out.println("before park");
// 等待获取许可
LockSupport.park("Park");
System.out.println("after park");
}

(2) park与interrupt

public void test3() throws Exception {
Thread thread = new Thread(() -> {
System.out.println(Thread.currentThread().isInterrupted()); // false
LockSupport.park();
System.out.println(Thread.currentThread().isInterrupted()); // true
});
thread.start(); TimeUnit.SECONDS.sleep(1);
thread.interrupt();
System.in.read();
}

简而言之:

  1. 实现机制和 wait/notify 有所不同,面向的是线程
  2. 不需要依赖监视器
  3. 与 wait/notify 没有交集
  4. 使用起来方便灵活

参考:

  1. 《LockSupport解析与使用》:https://blog.csdn.net/secsf/article/details/78560013

每天用心记录一点点。内容也许不重要,但习惯很重要!

并发编程(五)LockSupport的更多相关文章

  1. 【Java并发编程五】信号量

    一.概述 技术信号量用来控制能够同时访问某特定资源的活动的数量,或者同时执行某一给定操作的数据.计数信号量可以用来实现资源池或者给一个容器限定边界. 信号量维护了一个许可集,许可的初始量通过构造函数传 ...

  2. Java并发编程 (五) 线程安全性

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 一.安全发布对象-发布与逸出 1.发布与逸出定义 发布对象 : 使一个对象能够被当前范围之外的代码所使用 ...

  3. 【Java并发编程实战】----- AQS(三):阻塞、唤醒:LockSupport

    在上篇博客([Java并发编程实战]----- AQS(二):获取锁.释放锁)中提到,当一个线程加入到CLH队列中时,如果不是头节点是需要判断该节点是否需要挂起:在释放锁后,需要唤醒该线程的继任节点 ...

  4. 并发编程实践五:ReentrantLock

    ReentrantLock是一个可重入的相互排斥锁,实现了接口Lock,和synchronized相比,它们提供了同样的功能.但ReentrantLock使用更灵活.功能更强大,也更复杂.这篇文章将为 ...

  5. 并发编程(十五)——定时器 ScheduledThreadPoolExecutor 实现原理与源码深度解析

    在上一篇线程池的文章<并发编程(十一)—— Java 线程池 实现原理与源码深度解析(一)>中从ThreadPoolExecutor源码分析了其运行机制.限于篇幅,留下了Scheduled ...

  6. [Java并发编程(五)] Java volatile 的实现原理

    [Java并发编程(五)] Java volatile 的实现原理 简介 在多线程并发编程中 synchronized 和 volatile 都扮演着重要的角色,volatile 是轻量级的 sync ...

  7. java高并发编程(五)线程池

    摘自马士兵java并发编程 一.认识Executor.ExecutorService.Callable.Executors /** * 认识Executor */ package yxxy.c_026 ...

  8. Java并发编程原理与实战五:创建线程的多种方式

    一.继承Thread类 public class Demo1 extends Thread { public Demo1(String name) { super(name); } @Override ...

  9. 并发编程概述 委托(delegate) 事件(event) .net core 2.0 event bus 一个简单的基于内存事件总线实现 .net core 基于NPOI 的excel导出类,支持自定义导出哪些字段 基于Ace Admin 的菜单栏实现 第五节:SignalR大杂烩(与MVC融合、全局的几个配置、跨域的应用、C/S程序充当Client和Server)

    并发编程概述   前言 说实话,在我软件开发的头两年几乎不考虑并发编程,请求与响应把业务逻辑尽快完成一个星期的任务能两天完成绝不拖三天(剩下时间各种浪),根本不会考虑性能问题(能接受范围内).但随着工 ...

随机推荐

  1. HTML|CSS之CSS选择器及样式

    知识内容: 1.CSS选择器 2.CSS常用样式 参考:http://www.cnblogs.com/yuanchenqi/articles/5977825.html 一.CSS选择器 1.基础选择器 ...

  2. C中运算符

    01,条件表达式, int a = (b>118)?118:a = b; printf("%d\n",a);//指如果b的值是118,则就设置a的值为118,不然就将b的值赋 ...

  3. python编程之禅

    在python界面输入 import this >>> import this The Zen of Python, by Tim Peters Beautiful is bette ...

  4. leetcode965

    public class Solution { List<int> list = new List<int>(); private void postTree(TreeNode ...

  5. style css

    Title 语文 用户名 用户名 数学 英语 <!DOCTYPE html><html lang="en"><head> <meta ch ...

  6. 前端-javascript-正则表达式

    1.概念 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <titl ...

  7. heat 用法 示例

    heat.exe dir "./SampleFolder" -cg Files -dr INSTALLDIR -gg -g1 -sf -srd -var "var.Tar ...

  8. 状态图(Statechart Diagram)

    一.概念: 状态图用来描述一个特定对象的所有可能状态以及由于各种事件的发生而引起的状态之间的转移. 二.状态图的基本元素: 1.状态(State):指在对象的生命期中满足某些条件.执行某些活动或等待某 ...

  9. SQL Server - 最佳实践 - 参数嗅探问题 转。

    文章来自:https://yq.aliyun.com/articles/61767 先说我的问题,最近某个存储过程,暂定名字:sp_a 总是执行超时,sp_a带有一个参数,暂定名为 para1 var ...

  10. hadoop 集群安装配置 【转】

    http://www.cnblogs.com/ejiyuan/p/5557061.html 注意:要把master 上所有的配置文件(主要是配置的那四个 xxxx-site.xml 和 xxx-env ...