您好,登錄后才能下訂單哦!
Java并發(fā)編程中LockSupport的用法是怎樣的,相信很多沒有經(jīng)驗的人對此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個問題。
LockSupport是用于創(chuàng)建鎖和其他同步類的基本線程阻塞原語
LockSupport
提供了兩類最基本的API:
block線程類:一般都是以pack開頭的方法名,pack*(...)
pack方法有兩個重載的版本:blocker是一個對象,用于指定阻塞哪個對象。不知道的情況,默認以鎖對象自己this為blocker
public static void park(); public static void park(Object blocker);
拓展:parkNanos
函數(shù)
public static void parkNanos(Object blocker, long nanos) { if (nanos > 0) { // 獲取當前線程 Thread t = Thread.currentThread(); // 設置Blocker setBlocker(t, blocker); // 獲取許可,并設置了時間 UNSAFE.park(false, nanos); // 設置許可,重新設置blocker為null,避免unpack,獲取的blocker為之前設置的 setBlocker(t, null); } }
nanos參數(shù)表示相對時間,表示等待多長時間
parkUntil
函數(shù):表示在指定的時限前禁用當前線程,deadline參數(shù)表示絕對時間,表示指定的時間
public static void parkUntil(Object blocker, long deadline) { // 獲取當前線程 Thread t = Thread.currentThread(); // 設置Blocker setBlocker(t, blocker); UNSAFE.park(true, deadline); // 設置Blocker為null setBlocker(t, null); }
unBlock
線程類:unpack(Thread)
unpack方法用于釋放許可,指定線程可以繼續(xù)運行。
LockSupport是一個許可的信號量機制,pack消費,unpack放入,放入也是僅一個,不累計。例如,調(diào)用unpack放入一個信號量,多次調(diào)用,這個是不會累計信號量的,pack調(diào)用之后會消費
例子:如何控制兩個線程依次打印1、2、3、4、5、6、…
import java.util.concurrent.locks.LockSupport; public class LockSupportExample { private static final int total = 10; private static int i = 0; static Thread t1 , t2; public static void main(String[] args) { t1 = new Thread(() ->{ while (i < total) { System.out.println("t1:" + (++i)); LockSupport.unpark(t2); LockSupport.park(); } }); t2 = new Thread(() -> { while (i < total) { LockSupport.park(); System.out.println("t2:" + (++i)); LockSupport.unpark(t1); } }); t1.start(); t2.start(); } }
打?。?/p>
t1: 1
t2: 2
t1:3
t2:4
t1:5
t2:6
t1:7
t2:8
t1:9
t2:10
public class LockSupport { // 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實例 UNSAFE = sun.misc.Unsafe.getUnsafe(); // 線程類的class對象 Class<?> tk = Thread.class; // 獲取Thread的parkBlocker字段的內(nèi)存偏移地址 parkBlockerOffset = UNSAFE.objectFieldOffset (tk.getDeclaredField("parkBlocker")); // 獲取Thread的threadLocalRandomSeed字段的內(nèi)存偏移地址 SEED = UNSAFE.objectFieldOffset (tk.getDeclaredField("threadLocalRandomSeed")); // 獲取Thread的threadLocalRandomProbe字段的內(nèi)存偏移地址 PROBE = UNSAFE.objectFieldOffset (tk.getDeclaredField("threadLocalRandomProbe")); // 獲取Thread的threadLocalRandomSecondarySeed字段的內(nèi)存偏移地址 SECONDARY = UNSAFE.objectFieldOffset (tk.getDeclaredField("threadLocalRandomSecondarySeed")); } catch (Exception ex) { throw new Error(ex); } } }
pack方法的源碼:
public static void park(Object blocker) { // 獲取當前線程 Thread t = Thread.currentThread(); // 設置Blocker setBlocker(t, blocker); // 獲取許可 UNSAFE.park(false, 0L); // 重新可運行后再此設置Blocker為null,避免unpack獲取到上一個設置的setBlocker(t, blocker); setBlocker(t, null); }
unpack的源碼:
public static void unpark(Thread thread) { if (thread != null) // 線程為不空 UNSAFE.unpark(thread); // 釋放該線程許可 }
可以看出,不管是pack的源碼還是unpack的源碼都是通過Unsafe的底層api實現(xiàn)的
sun.misc.Unsafe
可以直接進行底層非安全操作的工具類
主要提供如下操作:
線程掛起與恢復
CAS操作
操縱對象屬性
操縱數(shù)組元素
直接操縱內(nèi)存
看完上述內(nèi)容,你們掌握Java并發(fā)編程中LockSupport的用法是怎樣的的方法了嗎?如果還想學到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。