这篇文章主要讲解了“Java LockSupport常用方法有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java LockSupport常用方法有哪些”吧!
LockSupport类常用方法源码
LockSupport只是一个简单的基础类,位于java.util.concurrent.locks包下,多用于线程的阻塞和唤醒,因此LockSupport也被称为其他线程的工具类。
LockSupport类的源码有标注,LockSupport类无法实例化。LockSupport类的底层是有Unsafe类实现的,LockSupport加载时的初始化也用到了Unsafe获取成员的偏移量,其源码如下:
// Hotspot implementation via intrinsics API private static final sun.misc.Unsafe UNSAFE; 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; 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); } }
LockSupport类中有一些核心的线程操作方法,多用于线程的阻塞与唤醒。
调用park()方法使线程阻塞:
public static void park(Object blocker) { Thread t = Thread.currentThread(); setBlocker(t, blocker); UNSAFE.park(false, 0L); setBlocker(t, null); } private static void setBlocker(Thread t, Object arg) { // Even though volatile, hotspot doesn't need a write barrier here. UNSAFE.putObject(t, parkBlockerOffset, arg); }
调用park(Object blocker)对传入的线程进行阻塞
public static void park(Object blocker) { Thread t = Thread.currentThread(); setBlocker(t, blocker); UNSAFE.park(false, 0L); setBlocker(t, null); }
在截止时间之前阻塞传入的某个线程:
public static void parkUntil(Object blocker, long deadline) { Thread t = Thread.currentThread(); setBlocker(t, blocker); UNSAFE.park(true, deadline); setBlocker(t, null); }
在nanos的时间范围内阻塞传入的线程:
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); } }
唤醒传入的线程:
public static void unpark(Thread thread) { if (thread != null) UNSAFE.unpark(thread); }
wait/notify方法和park/unpark方法区别
LockSupport类中的方法还有很多,在此先列举到这里。当我们看到阻塞和唤醒方法时,我们会联想到另一组唤醒方法wait()和notify(),这两组方法还是有所区别的。
这里直接记录下结论:wait和notify方法只能在同步代码块中使用(即必须与synchronized连用);必须先执行wait方法,然后再执行notify方法唤醒线程,调换顺序的话线程仍处于阻塞状态。
而park()和unpark()方法与之不同,这里可以通过代码运行结果来看:
package XIAOWEI;import java.util.concurrent.locks.LockSupport;public class Xiaowei{ public static void main(String[] args) { Thread A = new Thread(()-> { System.out.println("线程A已经被阻塞QWQ"); LockSupport.park(); System.out.println("线程A被线程B唤醒啦~~~"); }); A.start(); new Thread(()->{ System.out.println("线程B在唤醒线程A ing~~~"); LockSupport.unpark(A); },"B").start(); }}
那如果我们先通过线程B唤醒线程A,然后再让线程A阻塞呢(让线程A的阻塞休眠两秒)?
package XIAOWEI;import java.util.concurrent.locks.LockSupport;public class Xiaowei { public static void main(String[] args) { Thread A = new Thread(()-> { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程A已经被阻塞QWQ(第二版)"); LockSupport.park(); System.out.println("线程A被线程B唤醒啦~~~(第二版)"); }); A.start(); new Thread(()->{ System.out.println("线程B在唤醒线程A ing~~~驾驾驾"); LockSupport.unpark(A); },"B").start(); }}
由上面输出结果来看,虽然线程B先唤醒了线程A,然后线程A再开始阻塞,但是线程A还是处于唤醒状态,这是为什么呢?
接下来我找了段LockSupport类中的注释,其实有时看看注释也挺有意思的哈哈:
* <p>This class associates, with each thread that uses it, a permit
* (in the sense of the {@link java.util.concurrent.Semaphore
* Semaphore} class). A call to {@code park} will return immediately
* if the permit is available, consuming it in the process; otherwise
* it <em>may</em> block. A call to {@code unpark} makes the permit
* available, if it was not already available. (Unlike with Semaphores
* though, permits do not accumulate. There is at most one.)
这段话大意是说,LockSupport类使用permits这个东西来实现线程的阻塞和唤醒。每一个线程都会使用到(拥有)permit,且permit的值默认为0。接着它又说,这个概念和Semaphore信号量差不多,但是permit的值只有0和1两个值。哦~原来是这样。
对于上面例子,线程B调用unpark方法唤醒A后,会使得线程A的permit值为1,当线程调用park方法使自己阻塞时,发现自己已经有许可(permit)了,就会继续向下执行业务,而不会阻塞不动。
感谢各位的阅读,以上就是“Java LockSupport常用方法有哪些”的内容了,经过本文的学习后,相信大家对Java LockSupport常用方法有哪些这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!