LockSupport是一个工具类,提供了基本的线程阻塞和唤醒功能,它是建立锁和其余同步组件的基础工具,内部是使用sun.misc.Unsafe类实现的。ide
LockSupport和使用它的线程都会关联一个许可,park方法表示消耗一个许可,调用park方法时,若是许可可用则park方法返回,若是没有许可则一直阻塞直到许可可用。unpark方法表示增长一个许可,屡次调用并不会积累许可,由于许可数最大值为1。工具
park(): 阻塞当前线程,直到unpark方法被调用或当前线程被中断,park方法才会返回。线程
park(Object blocker): 同park()方法,多了一个阻塞对象blocker参数。对象
parkNanos(long nanos): 同park方法,nanos表示最长阻塞超时时间,超时后park方法将自动返回。blog
parkNanos(Object blocker, long nanos): 同parkNanos(long nanos)方法,多了一个阻塞对象blocker参数。同步
parkUntil(long deadline): 同park()方法,deadline参数表示最长阻塞到某一个时间点,当到达这个时间点,park方法将自动返回。(该时间为从1970年到如今某一个时间点的毫秒数)it
parkUntil(Object blocker, long deadline): 同parkUntil(long deadline)方法,多了一个阻塞对象blocker参数。io
unpark(Thread thread): 唤醒处于阻塞状态的线程thread。class
子线程执行LockSupport.park(),因为没有许可,进入阻塞状态。主线程3秒后调用unpark方法给子线程增长了一个许可,park方法返回,子线程被唤醒继续执行。thread
public class Demo { public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(() -> { System.out.println("do something start"); LockSupport.park(); System.out.println("do something end"); }); thread.start(); Thread.sleep(3000); System.out.println("给子线程thread增长一个许可"); LockSupport.unpark(thread); } } /* * 输出结果: * do something start * 给子线程thread增长一个许可 * do something end */
先unpark增长许可,后park消费许可也是能够的。unpark会给thread增长一个许可,此时调用park方法,因为许但是可用的,因此park方法直接返回了。
public class Demo { public static void main(String[] args) { Thread thread = new Thread(() -> { System.out.println("do something start"); System.out.println("子线程thread给本身增长一个许可"); LockSupport.unpark(Thread.currentThread()); LockSupport.park(); System.out.println("do something end"); }); thread.start(); } } /* * 输出结果: * do something start * 子线程thread给本身增长一个许可 * do something end */
连续调用unpark不会累计许可,许可最大值为1,第一次park就已经消耗了许可,因此第二次park一直阻塞。
public class Demo { public static void main(String[] args) { Thread thread = new Thread(() -> { System.out.println("do something start"); LockSupport.unpark(Thread.currentThread()); System.out.println("unpark 1"); LockSupport.unpark(Thread.currentThread()); System.out.println("unpark 2"); LockSupport.park(); System.out.println("park 1"); LockSupport.park(); System.out.println("park 2"); System.out.println("do something end"); }); thread.start(); } } /* * 输出结果: * do something start * unpark 1 * unpark 2 * park 1 */
经过前面方法介绍能够看到,park、parkNanos、parkUntil方法都有对应的带阻塞对象blocker参数的重载方法。Thread类有一个变量为parkBlocker,对应的就是LockSupport的park等方法设置进去的阻塞对象。
该参数主要用于问题排查和系统监控,在线程dump中会显示该参数的信息,有利于问题定位。
分别调用park()和park(Object blocker),而后使用jstack查看线程堆栈信息,对比发现后者会多输出一条阻塞对象的信息:
park():
public class Demo { public static void main(String[] args) { LockSupport.park(); } }
park(Object blocker):
public class Demo { public static void main(String[] args) { LockSupport.park(new Demo()); } }
park和unpark方法的调用不须要获取锁。
先调用unpark方法后调用park方法依然能够唤醒。
park方法响应中断,线程被中断后park方法直接返回,可是不会抛InterruptedException异常。
unpark方法是直接唤醒指定的线程。