最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java?LockSupport常用方法的源碼分析

 更新時(shí)間:2023年02月20日 14:04:37   作者:小威要向諸佬學(xué)習(xí)呀  
這篇文章主要為大家詳細(xì)介紹了Java?LockSupport類中的方法和部分源碼,以及面試常問到的一個(gè)小問題,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

LockSupport類常用方法源碼

LockSupport只是一個(gè)簡單的基礎(chǔ)類,位于java.util.concurrent.locks包下,多用于線程的阻塞和喚醒,因此LockSupport也被稱為其他線程的工具類。

LockSupport類的源碼有標(biāo)注,LockSupport類無法實(shí)例化。LockSupport類的底層是有Unsafe類實(shí)現(xiàn)的,LockSupport加載時(shí)的初始化也用到了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類中有一些核心的線程操作方法,多用于線程的阻塞與喚醒。

調(diào)用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);
    }

調(diào)用park(Object blocker)對傳入的線程進(jìn)行阻塞

    public static void park(Object blocker) {
        Thread t = Thread.currentThread();
        setBlocker(t, blocker);
        UNSAFE.park(false, 0L);
        setBlocker(t, null);
    }

在截止時(shí)間之前阻塞傳入的某個(gè)線程:

    public static void parkUntil(Object blocker, long deadline) {
        Thread t = Thread.currentThread();
        setBlocker(t, blocker);
        UNSAFE.park(true, deadline);
        setBlocker(t, null);
    }

在nanos的時(shí)間范圍內(nèi)阻塞傳入的線程:

    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方法區(qū)別

LockSupport類中的方法還有很多,在此先列舉到這里。當(dāng)我們看到阻塞和喚醒方法時(shí),我們會聯(lián)想到另一組喚醒方法wait()和notify(),這兩組方法還是有所區(qū)別的。

這里直接記錄下結(jié)論:wait和notify方法只能在同步代碼塊中使用(即必須與synchronized連用);必須先執(zhí)行wait方法,然后再執(zhí)行notify方法喚醒線程,調(diào)換順序的話線程仍處于阻塞狀態(tài)。

而park()和unpark()方法與之不同,這里可以通過代碼運(yùn)行結(jié)果來看:

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已經(jīng)被阻塞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已經(jīng)被阻塞QWQ(第二版)");
            LockSupport.park();
            System.out.println("線程A被線程B喚醒啦~~~(第二版)");
        });
        A.start();
        new Thread(()->{
            System.out.println("線程B在喚醒線程A ing~~~駕駕駕");
            LockSupport.unpark(A);
        },"B").start();
    }
}

由上面輸出結(jié)果來看,雖然線程B先喚醒了線程A,然后線程A再開始阻塞,但是線程A還是處于喚醒狀態(tài),這是為什么呢?

接下來我找了段LockSupport類中的注釋,其實(shí)有時(shí)看看注釋也挺有意思的哈哈:

 * <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這個(gè)東西來實(shí)現(xiàn)線程的阻塞和喚醒。每一個(gè)線程都會使用到(擁有)permit,且permit的值默認(rèn)為0。接著它又說,這個(gè)概念和Semaphore信號量差不多,但是permit的值只有0和1兩個(gè)值。哦~原來是這樣。

對于上面例子,線程B調(diào)用unpark方法喚醒A后,會使得線程A的permit值為1,當(dāng)線程調(diào)用park方法使自己阻塞時(shí),發(fā)現(xiàn)自己已經(jīng)有許可(permit)了,就會繼續(xù)向下執(zhí)行業(yè)務(wù),而不會阻塞不動(dòng)。

到此這篇關(guān)于Java LockSupport常用方法的源碼分析的文章就介紹到這了,更多相關(guān)Java LockSupport內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Idea進(jìn)行pull的時(shí)候Your local changes would be overwritten by merge.

    Idea進(jìn)行pull的時(shí)候Your local changes would be

    這篇文章主要介紹了Idea進(jìn)行pull的時(shí)候Your local changes would be overwritten by merge.具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • 堆排序算法的講解及Java版實(shí)現(xiàn)

    堆排序算法的講解及Java版實(shí)現(xiàn)

    這篇文章主要介紹了堆排序算法的講解及Java版實(shí)現(xiàn),堆排序基于堆這種數(shù)據(jù)結(jié)構(gòu),在本文中對堆的概念也有補(bǔ)充介紹,需要的朋友可以參考下
    2016-05-05
  • 詳解Java的類加載機(jī)制及熱部署的原理

    詳解Java的類加載機(jī)制及熱部署的原理

    今天我要講的就是Java的熱部署的原理,由于熱部署的原理和類的加載機(jī)制有關(guān),所以打算講一下類加載的機(jī)制,文中介紹的非常詳細(xì),需要的朋友可以參考下
    2021-05-05
  • Spring Boot Admin實(shí)現(xiàn)服務(wù)健康預(yù)警功能

    Spring Boot Admin實(shí)現(xiàn)服務(wù)健康預(yù)警功能

    這篇文章主要介紹了Spring Boot Admin實(shí)現(xiàn)服務(wù)健康預(yù)警功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-05-05
  • IDEA中使用Typora編輯md文件的方法

    IDEA中使用Typora編輯md文件的方法

    這篇文章主要介紹了IDEA中使用Typora編輯md文件的方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-09-09
  • mybatis update set 多個(gè)字段實(shí)例

    mybatis update set 多個(gè)字段實(shí)例

    這篇文章主要介紹了mybatis update set 多個(gè)字段實(shí)例,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-01-01
  • Java執(zhí)行hadoop的基本操作實(shí)例代碼

    Java執(zhí)行hadoop的基本操作實(shí)例代碼

    這篇文章主要介紹了Java執(zhí)行hadoop的基本操作實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下
    2017-04-04
  • Spring Boot2開發(fā)之Spring Boot整合Shiro兩種詳細(xì)方法

    Spring Boot2開發(fā)之Spring Boot整合Shiro兩種詳細(xì)方法

    這篇文章主要介紹了Spring Boot2開發(fā)之Spring Boot整合Shiro詳細(xì)方法,需要的朋友可以參考下
    2020-03-03
  • Spring Boot線程池使用的一些實(shí)用心得

    Spring Boot線程池使用的一些實(shí)用心得

    理論上線程越多程序可能更快,但在實(shí)際使用中我們需要考慮到線程本身的創(chuàng)建以及銷毀的資源消耗,以及保護(hù)操作系統(tǒng)本身的目的我們通常需要將線程限制在一定的范圍之類,這篇文章主要給大家介紹了關(guān)于Spring Boot線程池使用的一些實(shí)用心得,需要的朋友可以參考下
    2021-09-09
  • SPRINGBOOT讀取PROPERTIES配置文件數(shù)據(jù)過程詳解

    SPRINGBOOT讀取PROPERTIES配置文件數(shù)據(jù)過程詳解

    這篇文章主要介紹了SPRINGBOOT讀取PROPERTIES配置文件數(shù)據(jù)過程詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-12-12

最新評論

武义县| 家居| 石门县| 海晏县| 宣汉县| 芒康县| 合阳县| 阿荣旗| 清镇市| 赤城县| 台东市| 阳西县| 满城县| 景宁| 乐亭县| 楚雄市| 容城县| 南宫市| 融水| 新和县| 瑞金市| 科技| 钦州市| 临高县| 丰顺县| 名山县| 勃利县| 建瓯市| 喀喇| 罗定市| 房产| 遂平县| 海盐县| 荣成市| 武清区| 会理县| 南充市| 连江县| 徐闻县| 成武县| 监利县|