并发编程之 线程协作工具 LockSupport

前言
在前面的文章中,我们介绍了并发工具中的4个,Samephore,CyclicBarrier,CountDownLatch,Exchanger,但是我们漏了一个,非常的好用的工具,楼主在这里必须加上。
LockSupport
LockSupport 是一个非常方便实用的线程阻塞工具,他可以在任意位置让线程阻塞。并且是静态的方法。是不是很心动?
LockSupport 的静态方法 park()可以阻塞当前线程,类似的还有 parkNanos(),parkUntil()等,他们实现了一个限时的等待。
同样的,有阻塞的方法,当然有唤醒的方法,什么呢?unpark(Thread) 方法。该方法可以将指定线程唤醒。
我们还是来一个例子吧,看看到底有多好用:
public class LockSupportInterruptDemo {
static Object u = new Object();
static ChangeObjectThread t1 = new ChangeObjectThread("t1");
static ChangeObjectThread t2 = new ChangeObjectThread("t2");
static class ChangeObjectThread extends Thread {
public ChangeObjectThread(String name) {
super.setName(name);
}
public void run() {
synchronized (u) {
System.out.println("in " + getName());
// wait
LockSupport.park();
if (Thread.interrupted()) {
System.err.println(getName() + "被中断了");
}
}
System.out.println(getName() + "执行结束了");
}
}
public static void main(String[] args) throws InterruptedException {
t1.start();
Thread.sleep(1000);
t2.start();
Thread.sleep(3000);
t1.interrupt();
// notify
LockSupport.unpark(t2);
}
}
执行结果:

完全实现了 wait notify 的功能,但是,请注意,park 方法和 wait 方法相比,不需要获取某个对象的锁,也不会抛出 InterruptedException 异常,因此,你需要像我们的例子一样,使用静态方法进行判断。
如果你将 park 方法改成 park(this)/park(Thread),那么在打印 线程dump 信息的时候会打印阻塞对象的详细信息。

该方法和 Lock 接口一样都是使用的 sun.misc.Unsafe 的 park 方法实现的阻塞。
还有一个需要注意的是:park 方法和 unpark 方法执行顺序不是那么的严格。比如我们在 Thread 类中提到的 suspend 方法 和resume 方法,如果顺序错误,将导致永远无法唤醒,但 park 方法和 unpark 方法则不会,我们测试一下,将 unpark 方法紧跟着 start 方法后面执行,那么也就是说,unpark 方法在 线程2 的park 方法之前执行,但结果相同。

我们将 unpark 方法移动到了 start 方法后面,依然正确执行。
什么原因呢?这是因为 LockSupport 使用了类似信号量的机制。他为每一个线程准备了一个许可(默认不可用),如果许可能用,那么 park 函数会立即返回,并且消费这个许可(也就是将许可变为不可用),如果许可不可用,将会阻塞。而 unpark 方法则使得一个许可变为可用(但是和信号量不同的是,许可不能累加,你不可能拥有超过要给许可,他永远只有一个)。
下面是JDK文档:


这个特定使得:即使 unpark 方法在 park 方法之前执行,他也可以使下一次的 park 操作立即返回。这也使上面的代码能正确执行的原因。
好了,到这里,LockSupport 就介绍完了,可以说,该方法可以替代 wait ,notify ,Condition 的 await ,signal 方法。注意,这里的 park 方法底层和 Lock 的底层实现是一致的。都是掉哟个 sun.misc.Unsafe。这个类可以说很牛逼。
good luck !!!!
并发编程之 线程协作工具 LockSupport的更多相关文章
- Java并发编程:线程间协作的两种方式:wait、notify、notifyAll和Condition
Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者 ...
- Java 并发编程:线程间的协作(wait/notify/sleep/yield/join)
Java并发编程系列: Java 并发编程:核心理论 Java并发编程:Synchronized及其实现原理 Java并发编程:Synchronized底层优化(轻量级锁.偏向锁) Java 并发编程 ...
- 19、Java并发编程:线程间协作的两种方式:wait、notify、notifyAll和Condition
Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者 ...
- Java并发编程:线程控制
在上一篇文章中(Java并发编程:线程的基本状态)我们介绍了线程状态的 5 种基本状态以及线程的声明周期.这篇文章将深入讲解Java如何对线程进行状态控制,比如:如何将一个线程从一个状态转到另一个状态 ...
- python并发编程之线程/协程
python并发编程之线程/协程 part 4: 异步阻塞例子与生产者消费者模型 同步阻塞 调用函数必须等待结果\cpu没工作input sleep recv accept connect get 同 ...
- Java并发编程:线程池的使用
Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...
- 并发编程 13—— 线程池的使用 之 配置ThreadPoolExecutor 和 饱和策略
Java并发编程实践 目录 并发编程 01—— ThreadLocal 并发编程 02—— ConcurrentHashMap 并发编程 03—— 阻塞队列和生产者-消费者模式 并发编程 04—— 闭 ...
- Scala 深入浅出实战经典 第68讲:Scala并发编程原生线程Actor、Cass Class下的消息传递和偏函数实战解析
王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载: 百度云盘:http://pan.baidu.com/s/1c0noOt ...
- Java并发编程:线程池的使用(转)
Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...
随机推荐
- Flashcache基本使用及注意事项
Flashcache基本使用及注意事项 发表回复 环境:Centos6.5 x64 minal 安装方法 Contents [hide] 1 安装方法 2 自动加载模块 3 创建Flashcache ...
- 使用C#写MVC框架(一:核心原理)
目录: 一.MVC原理解析 二.HttpHandler 1.HttpHandler,IHttpHandler,MvcHandler的说明 2.IHttpHandler解析 3.MvcHandler解析 ...
- AEAI DP开发统计分析
1 背景概述 平时做统计分析都是调rest服务,给前台提供数据,然后在管理控制台里配置portlet.但并不是所有的项目都会用到portal,这时就需要在AEAI DP应用开发平台里开发统计分析了,下 ...
- python------virtualenv&virtualenvwrapper的使用
virtualenv virtualenv 的作用:为单个项目创建独立的python虚拟环境 virtualenv的使用 : 1.通过如下命令安装virtualenv $ sudo pip insta ...
- iOS 数据持久化-- FMDB
一.简介 1.什么是FMDB FMDB是iOS平台的SQLite数据库框架 FMDB以OC的方式封装了SQLite的C语言API 2.FMDB的优点 使用起来更加面向对象,省去了很多麻烦.冗余的C语言 ...
- 设置iptables NAT出外网
有时候云上部署环境,不能动态自设路由,没有公网ip地址的服务器,只能通过NAT的方式出外网,下面就记录一下设置过程. 当前状态 服务器A只有一个内网IP,不能上外网,内网IP与服务器B内网相通:服务器 ...
- centos7搭建kafka集群-第二篇
好了,本篇开始部署kafka集群 Zookeeper集群搭建 注:Kafka集群是把状态保存在Zookeeper中的,首先要搭建Zookeeper集群(也可以用kafka自带的ZK,但不推荐) 1.软 ...
- 【sping揭秘】2、关于spring配置文件
<import>标签 引入其他的配置文件,如果A.xml 中的<bean>定义可能依赖B.xml中的某些<bean>定义,那么可以再A.xml中使用这种方式< ...
- 下载一个新的app之后,如果分析、鉴赏?
一直对新的事物还是比较好奇的,所以希望以后每隔几天就下载一个app,去体验,但是之前体验的时候,都是大概看看功能.竞品分析.流畅度等等,却没有一个完整的方法论,所以,这篇文章就是总结一下更为具体的方法 ...
- [转]php实时输出内容
b开发中有没有碰到需要适时的将结果输出到浏览器页面而不刷新整个页面的需求呢?当你在处理一个过程需要耗时很长,但你又需要适时的知道程序当前的处理状况的时候,该怎么办呢?下面就分享一下如何使用php及时的 ...