JDK版本: 1.8java
LockSupport类主要提供了park和unpark两个native方法,用于阻塞和唤醒线程。注释中有这么一段:并发
这个类是为拥有更高级别抽象的并发类服务的,开发中咱们不会用到这个类dom
既然只是native方法,开发中也用不到,那么还有必要去看么?工具
了解LockSupport能够帮助咱们更好理解并发,并且你们熟悉的并发中最核心的AQS类中也大量的使用了LockSupport,因此仍是有必要看一看的,至少熟悉其中的概念。this
已经知道了这个类就是阻塞唤醒,Object.wait和Object.notify,Thread.suspend和Thread.resume这两对方法也是相似效果,那么还有必要去看么???线程
LockSupport会有上面的问题么,又有哪些特色呢,让咱们进入源码code
package java.util.concurrent.locks; public class LockSupport { // 工具类,ban掉构造 private LockSupport() {} private static final sun.misc.Unsafe UNSAFE; // parkBlocker的内存偏移量 private static final long parkBlockerOffset; private static final long SEED; private static final long PROBE; private static final long SECONDARY; static { try { UNSAFE = sun.misc.Unsafe.getUnsafe(); Class<?> tk = Thread.class; // 反射拿到Thread类中的parkBlocker属性,而后获取其在内存中的偏移量 parkBlockerOffset = UNSAFE.objectFieldOffset (tk.getDeclaredField("parkBlocker")); SEED = UNSAFE.objectFieldOffset (tk.getDeclaredField("threadLocalRandomSeed")); PROBE = UNSAFE.objectFieldOffset (tk.getDeclaredField("threadLocalRandomProbe")); SECONDARY = UNSAFE.objectFieldOffset (tk.getDeclaredField("threadLocalRandomSecondarySeed")); } catch (Exception ex) { throw new Error(ex); } } }
// 最简单的方式,可是不推荐 public static void park() { /** * 将当前线程挂起,是经过二元信号量,获取许可证明现的,拿到许可证后才执行挂起 * 不是基于对象的监视器锁,因此不须要显示的同步 * 若是超时了,被中断了或者unpark了就会return而且释放许可证 * 须要注意的是和wait同样也会由于JVM内部未知缘由return,因此咱们若是使用也须要放在循环内 * 第一个参数 flase表明纳秒级别超时控制,此级别下第二个参数timeout为0表明无限等待 * 第一个参数 true表明毫秒级别超时控制,此级别下第二个参数timeout为0会当即返回 */ UNSAFE.park(false, 0L); } // 推荐方式,blocker是个辅助对象,用于跟踪许可证的获取,以及定位一些阻塞问题,通常状况park(this)就行 public static void park(Object blocker) { Thread t = Thread.currentThread(); // 标记对于当前线程t,blocker正在获取许可证,出问题经过getBlocker方法去定位 setBlocker(t, blocker); UNSAFE.park(false, 0L); // park操做return了,标记许可证已经释放 setBlocker(t, null); } private static void setBlocker(Thread t, Object arg) { // 经过偏移量,把给当前线程t的parkBlocker属性赋值为arg UNSAFE.putObject(t, parkBlockerOffset, arg); }
相信你们已经基本了解park操做了,LockSupport还给咱们提供了其余功能对象
// 推荐,纳秒级别timeout后return 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); } } // 推荐,毫秒级别timeout后return public static void parkUntil(Object blocker, long deadline) { Thread t = Thread.currentThread(); setBlocker(t, blocker); UNSAFE.park(true, deadline); setBlocker(t, null); } // 不推荐,纳秒级别timeout后return public static void parkNanos(long nanos) { if (nanos > 0) UNSAFE.park(false, nanos); } // 不推荐,毫秒级别timeout后return public static void parkUntil(long deadline) { UNSAFE.park(true, deadline); }
public static void unpark(Thread thread) { if (thread != null) //释放线程thread的许可证,若是已是释放状态那就什么都不会发生,由于总共就1个许可,因此unpark能够先于park执行没有任务问题 UNSAFE.unpark(thread); }
// 因为包权限问题从ThreadLocalRandom类中copy过来的,用于生成随机数种子 static final int nextSecondarySeed() { int r; Thread t = Thread.currentThread(); if ((r = UNSAFE.getInt(t, SECONDARY)) != 0) { r ^= r << 13; // xorshift r ^= r >>> 17; r ^= r << 5; } else if ((r = java.util.concurrent.ThreadLocalRandom.current().nextInt()) == 0) r = 1; // avoid zero UNSAFE.putInt(t, SECONDARY, r); return r; }
public class LockSupportTest { public static void main(String[] args) { AtomicBoolean flag = new AtomicBoolean(true); Thread thread = new Thread(() -> { Thread curr = Thread.currentThread(); System.out.println("线程1 即将被阻塞"); while (flag.get()) { LockSupport.park(curr); System.out.println("线程1 复活"); } System.out.println("线程1 结束使命"); }); thread.start(); new Thread(() -> { System.out.println("唤醒线程1"); flag.compareAndSet(true, false); LockSupport.unpark(thread); }).start(); } /** * 输出: * 线程1 即将被阻塞 * 唤醒线程1 * 线程1 复活 * 线程1 结束使命 */ }