您好,登錄后才能下訂單哦!
這篇文章主要講解了“Java LockSupport常用方法有哪些”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Java 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); }
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常用方法有哪些這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。