中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java?LockSupport常用方法有哪些

發布時間:2023-02-24 17:45:33 來源:億速云 閱讀:86 作者:iii 欄目:開發技術

這篇文章主要講解了“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();
    }
}

Java?LockSupport常用方法有哪些

那如果我們先通過線程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();
    }
}

Java?LockSupport常用方法有哪些

由上面輸出結果來看,雖然線程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常用方法有哪些這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

水城县| 鞍山市| 布尔津县| 婺源县| 呈贡县| 甘孜| 台江县| 高邮市| 清水县| 淄博市| 满洲里市| 大新县| 乳源| 龙口市| 涪陵区| 宁城县| 团风县| 墨玉县| 北京市| 常山县| 公安县| 攀枝花市| 武邑县| 邯郸县| 芜湖市| 莱州市| 石台县| 江陵县| 弋阳县| 仙居县| 南漳县| 霞浦县| 同江市| 山西省| 泽库县| 全州县| 固镇县| 杂多县| 岳西县| 五指山市| 云安县|