LockSupport
当需要阻塞或唤醒一个线程的时候,都会使用LockSupport工具类来完成相应 工作。LockSupport定义了一组的公共静态方法,这些方法提供了最基本的线程阻塞和唤醒功 能,而LockSupport也成为构建同步组件的基础工具。
- LockSupport 是用来创建锁和其他同步类的基本线程阻塞原语
LockSupport方法介绍
方法 | 说明 |
void park() | 阻塞当前线程,如果调用unpark方法或者当前线程被中断,从能从park()方法中返回 |
void park(Object blocker) | 入参增加一个Object对象,用来记录导致线程阻塞的阻塞对象,方便进行问题排查 |
void parkNanos (long nanos) | 阻塞当前线程,最长不超过nanos纳秒,增加了超时返回的特性 |
void parkNanos (Object blocker, long nanos) | 入参增加一个Object对象,用来记录导致线程阻塞的阻塞对象,方便进行问题排查 |
void parkUntil(long deadline) | 阻塞当前线程,知道deadline |
voidparkUntil (Object blocker, long deadline) | 入参增加一个Object对象,用来记录导致线程阻塞的阻塞对象,方便进行问题排查 |
void unpark(Thread thread) | 唤醒处于阻塞状态的指定线程 |
LockSupport底层代码实现
通过阅读源代码我们可以发现,LockSupport中关于线程的阻塞和唤醒,主要调用的是sun.misc.Unsafe 中的park(boolean isAbsolute, long time)
与unpark(Object thread)
方法
实列:
import java.util.concurrent.locks.LockSupport; public class myLockSupport { public static void main(String[] args) { Thread thread = new Thread(() -> { //阻塞当前线程 LockSupport.park(); //阻塞 后下面不走了 System.out.println(Thread.currentThread().getName() + "被唤醒"); }); thread.start(); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().isAlive()+" "+Thread.currentThread().getName()); //唤醒处于阻塞状态的指定线程 //LockSupport.unpark(thread); } }
结果:true main
加入唤醒
public class myLockSupport { public static void main(String[] args) { Thread thread = new Thread(() -> { //阻塞当前线程 LockSupport.park(); //阻塞 后下面不走了 System.out.println(Thread.currentThread().getName() + "被唤醒"); }); thread.start(); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().isAlive()+" "+Thread.currentThread().getName()); //唤醒处于阻塞状态的指定线程 LockSupport.unpark(thread); } }
结果:
true main
Thread-0被唤醒
与 wait()、notify() 的区别
- 面向的主体不一样。
- LockSupport 主要是针对 Thread 进进行阻塞处理,可以指定阻塞队列的目标对象,每次可以指定具体的线程唤醒。
- Object.wait() 是以对象为纬度,阻塞当前的线程和唤醒单个(随机)或者所有线程。
- 实现机制不同。
- 虽然 LockSupport 可以指定 Monitor 的 object 对象,但和 object.wait() 两者的阻塞队列并不交叉。
- LockSupport 阻塞和解除阻塞线程直接操作的是 Thread。而 Object 的 wait/notify 并不是直接对线程操作,是被动的方法,需要一个 Object 来进行线程的挂起或唤醒。
- Thead 在调用 wait 之前,当前线程必须先获得该对象的监视器(syschronized),被唤醒之后需要重新获取到监视器才能继续执行。而 LockSupport 可以随意进行 park 或者 unpark。