Java并发编程 LockSupport源码分析
这个类比较简单,是一个静态类,不需要实例化直接使用,底层是通过java未开源的Unsafe直接调用底层操作系统来完成对线程的阻塞。
package java.util.concurrent.locks;
import java.util.concurrent.*;
import sun.misc.Unsafe; public class LockSupport {
private LockSupport() {} //这个类是java未开源的类,直接调用底层操作系统
private static final Unsafe unsafe = Unsafe.getUnsafe();
//记录线程对象中parkBlocker字段的位置
private static final long parkBlockerOffset; static {
try {
parkBlockerOffset = unsafe.objectFieldOffset
(java.lang.Thread.class.getDeclaredField("parkBlocker"));
} catch (Exception ex) { throw new Error(ex); }
} private static void setBlocker(Thread t, Object arg) {
// Even though volatile, hotspot doesn't need a write barrier here.
//将org设置到线程的parkBlocker字段上
//这样方便在测试的时候知道线程在什么地方阻塞
unsafe.putObject(t, parkBlockerOffset, arg);
} //调用底层操作系统解锁线程
public static void unpark(Thread thread) {
if (thread != null)
unsafe.unpark(thread);
} //设置blocker并且锁定线程
public static void park(Object blocker) {
Thread t = Thread.currentThread();
setBlocker(t, blocker);
unsafe.park(false, 0L);
setBlocker(t, null);
} //设置blocker并且并且阻塞线程nanos纳秒 可以这么转换成毫秒
//TimeUnit timeUnit = TimeUnit.MILLISECONDS;
//LockSupport.parkNanos(timeUnit.toNanos(3000));
public static void parkNanos(Object blocker, long nanos) {
if (nanos > 0) {
Thread t = Thread.currentThread();
setBlocker(t, blocker);
unsafe.park(false, nanos);
setBlocker(t, null);
}
} //设置blocker并且阻塞线程多少毫秒
//注意这里的时间需要使用系统时间加上需要等待的时间
//LockSupport.parkUntil(System.currentTimeMillis() + 3000);
public static void parkUntil(Object blocker, long deadline) {
Thread t = Thread.currentThread();
setBlocker(t, blocker);
unsafe.park(true, deadline);
setBlocker(t, null);
} //获得线程阻塞时设置的Blocker
public static Object getBlocker(Thread t) {
if (t == null)
throw new NullPointerException();
return unsafe.getObjectVolatile(t, parkBlockerOffset);
} //阻塞线程
public static void park() {
unsafe.park(false, 0L);
} public static void parkNanos(long nanos) {
if (nanos > 0)
unsafe.park(false, nanos);
} public static void parkUntil(long deadline) {
unsafe.park(true, deadline);
}
}
写一个简单DEMO,这个类使用起来也很简单,一般很少直接使用,java.util.concurrent包里有很多锁的实现都是基于此类,后续我们会讲到。
public static void main(String[] args) {
final Thread mainThread = Thread.currentThread();
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("3秒后解锁主线程");
try {
Thread.sleep(3000);
LockSupport.unpark(mainThread);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread.start();
LockSupport.park();
System.out.println("Demo.main()");
}
Java并发编程 LockSupport源码分析的更多相关文章
- Java并发编程-ReentrantLock源码分析
一.前言 在分析了 AbstractQueuedSynchronier 源码后,接着分析ReentrantLock源码,其实在 AbstractQueuedSynchronizer 的分析中,已经提到 ...
- Java并发编程 ReentrantLock 源码分析
ReentrantLock 一个可重入的互斥锁 Lock,它具有与使用 synchronized 方法和语句所访问的隐式监视器锁相同的一些基本行为和语义,但功能更强大. 这个类主要基于AQS(Abst ...
- Java并发编程-AbstractQueuedSynchronizer源码分析
简介 提供了一个基于FIFO队列,可以用于构建锁或者其他相关同步装置的基础框架.该同步器(以下简称同步器)利用了一个int来表示状态,期望它能够成为实现大部分同步需求的基础.使用的方法是继承,子类通过 ...
- java 并发编程——Thread 源码重新学习
Java 并发编程系列文章 Java 并发基础——线程安全性 Java 并发编程——Callable+Future+FutureTask java 并发编程——Thread 源码重新学习 java并发 ...
- Java异步编程——深入源码分析FutureTask
Java的异步编程是一项非常常用的多线程技术. 之前通过源码详细分析了ThreadPoolExecutor<你真的懂ThreadPoolExecutor线程池技术吗?看了源码你会有全新的认识&g ...
- Java并发-ConcurrentModificationException原因源码分析与解决办法
一.异常原因与异常源码分析 对集合(List.Set.Map)迭代时对其进行修改就会出现java.util.ConcurrentModificationException异常.这里以ArrayList ...
- 并发编程—— FutureTask 源码分析
1. 前言 当我们在 Java 中使用异步编程的时候,大部分时候,我们都会使用 Future,并且使用线程池的 submit 方法提交一个 Callable 对象.然后调用 Future 的 get ...
- 并发编程 —— Timer 源码分析
前言 在平时的开发中,肯定需要使用定时任务,而 Java 1.3 版本提供了一个 java.util.Timer 定时任务类.今天一起来看看这个类. 1.API 介绍 Timer 相关的有 3 个类: ...
- Java并发指南10:Java 读写锁 ReentrantReadWriteLock 源码分析
Java 读写锁 ReentrantReadWriteLock 源码分析 转自:https://www.javadoop.com/post/reentrant-read-write-lock#toc5 ...
随机推荐
- hibernate的native sql查询
在我们的hibernate中,除了我们常用的HQL查询以外,还非常好的支持了原生的SQL查询,那么我们既然使用了hibernate,为什么不都采用hibernate推荐的HQL查询语句呢?这是因为HQ ...
- Android工具类-关于网络、状态的工具类
下方是一个很好的监测网络.状态的工具类 public class NetworkUtils { /** * 网络是否可用 * * @param activity * @return */ public ...
- Android下Notification,样式style,主题theme的功能实现
一:Notification 1.NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVIC ...
- [转]使用spring中的@Transactional注解时,可能需要注意的地方
前情提要 在编写业务层方法时,会遇到很多需要事务提交的操作,spring框架为我们提供很方便的做法,就是在需要事务提交的方法上添加@Transactional注解,比起我们自己开启事务.提交以及控制回 ...
- Knockout: 让ViewModel从htm中剥离出去。
在一些Knockout例子中,直接在htm中添加scripts写viewmodel,如何能将让ViewModel从htm中剥离出去呢?从knockout官网上找到了解决方法,如下: 1.knockou ...
- C#基础第一天-作业
1.从键盘上输入三个数,用if语句和逻辑表达式把最大数找出来.2.从键盘上输入三个数,用if语句和逻辑表达式把最小数找出来.3.输入一个成绩(0-100),然后用if else语句判断该成绩是优.良. ...
- 使用 http 请求方式获取 eureka server的服务信息
对于一些系统不能接入 eureka server,又需要访问接入eureka server 的服务. 方法一:直接调用服务的地址是一种实现方式,弊端就是地址是写死的,万一服务地址变更则访问不到. 方法 ...
- Zephir入门 —— 语法篇
概述 Zephir的语法跟PHP很相似,所以这里不会把官网的文档照搬过来翻译一遍,而是会把一些Zephir相较于PHP比较特别的语法挑出来讲一下.如果想要要完整学习Zephir的语法,没有比官网的文档 ...
- 设置 debug 版本签名与生产版本一致
debug 版本使用生产版本的签名 在开发过程中,app 直接跑到手机上,用的签名文件是 Android Studio 默认的自动生成的一个签名,与生产版本的 app 签名是不一样的.当接入华为推送的 ...
- Universal USB Installer集开源软件之佳作
有机会下载一份uui的源代码,翻看了一下,呵呵,有意思,几乎是一个开源软件的大杂烩,忽然,恍然大悟,原来,作者才是开源软件精神的代言人,不重复制造轮子的践行者啊. uui网址:https://www. ...