前言

在前面的文章中,我们介绍了并发工具中的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的更多相关文章

  1. Java并发编程:线程间协作的两种方式:wait、notify、notifyAll和Condition

    Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者 ...

  2. Java 并发编程:线程间的协作(wait/notify/sleep/yield/join)

    Java并发编程系列: Java 并发编程:核心理论 Java并发编程:Synchronized及其实现原理 Java并发编程:Synchronized底层优化(轻量级锁.偏向锁) Java 并发编程 ...

  3. 19、Java并发编程:线程间协作的两种方式:wait、notify、notifyAll和Condition

    Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者 ...

  4. Java并发编程:线程控制

    在上一篇文章中(Java并发编程:线程的基本状态)我们介绍了线程状态的 5 种基本状态以及线程的声明周期.这篇文章将深入讲解Java如何对线程进行状态控制,比如:如何将一个线程从一个状态转到另一个状态 ...

  5. python并发编程之线程/协程

    python并发编程之线程/协程 part 4: 异步阻塞例子与生产者消费者模型 同步阻塞 调用函数必须等待结果\cpu没工作input sleep recv accept connect get 同 ...

  6. Java并发编程:线程池的使用

    Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...

  7. 并发编程 13—— 线程池的使用 之 配置ThreadPoolExecutor 和 饱和策略

    Java并发编程实践 目录 并发编程 01—— ThreadLocal 并发编程 02—— ConcurrentHashMap 并发编程 03—— 阻塞队列和生产者-消费者模式 并发编程 04—— 闭 ...

  8. Scala 深入浅出实战经典 第68讲:Scala并发编程原生线程Actor、Cass Class下的消息传递和偏函数实战解析

    王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载: 百度云盘:http://pan.baidu.com/s/1c0noOt ...

  9. Java并发编程:线程池的使用(转)

    Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...

随机推荐

  1. 8.正则表达式和XPath

    1.使用正则表达式爬取内涵段子 import requests import re def loadPage(page): url = "http://www.neihan8.com/art ...

  2. https://www.cnblogs.com/hnxxcxg/p/6085149.html

    DELPHI微信支付代码   不管是微信支付还是支付宝支付, 3个最棘手的问题是:1,如何生成签名2,支付请求如何提交3, 如何验证签名 下面就围绕这二个问题来讲. 我使用的是XE3. 先看微信支付: ...

  3. hdu 1.3.3 今年暑假不AC

    //简单.... 1 #include<iostream> #include<cstdio> #include<cstdlib> using namespace s ...

  4. MVC图片验证

    1.创建一个验证类,里面有生成验证码的两个方法. namespace YTJWGL_Common { public class ValidatorCodeTools { #region 生成校验码图片 ...

  5. bootstrap基础学习小记(三)网格简介

    网格系统:网格系统的实现原理非常简单,仅仅是通过定义容器大小,平分12份(也有平分成24份或32份,但12份是最常见的),再调整内外边距,最后结合媒体查询,就制作出了强大的响应式网格系统.Bootst ...

  6. NET npoi帮助类

    nuget添加npoi /// <summary> /// npoi帮助类 /// </summary> public static class NpoiHelper { // ...

  7. react项目开发中遇到的问题

    前言 作为一个前端爱好者来说,都想在react上一试生手,那么在搭建react项目开发时,肯定会有这样或者那样的问题,尤其是对初学者来说,下面就个人在开发过程中遇到的问题总结一下,好在有google帮 ...

  8. Spring 扫描标签<context:component-scan/>

    一. <context:annotation-config/> 此标签支持一些注入属性的注解, 列如:@Autowired, @Resource注解 二. <context:comp ...

  9. [JavaScript] html5 video标签注意事项

    Chrome 66 禁止声音自动播放 声音无法自动播放这个在IOS/Android上面一直是个惯例,桌面版的Safari在2017年的11版本也宣布禁掉带有声音的多媒体自动播放功能,紧接着在2018年 ...

  10. python进程——生产者消费者

    生产者消费者模型介绍 为什么要使用生产者消费者模型 生产者指的是生产数据的任务,消费者指的是处理数据的任务,在并发编程中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完 ...