亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

LockSupport類(lèi)常用方法源碼

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

LockSupport類(lèi)的源碼有標(biāo)注,LockSupport類(lèi)無(wú)法實(shí)例化。LockSupport類(lèi)的底層是有Unsafe類(lèi)實(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類(lèi)中有一些核心的線程操作方法,多用于線程的阻塞與喚醒。

調(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)對(duì)傳入的線程進(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類(lèi)中的方法還有很多,在此先列舉到這里。當(dāng)我們看到阻塞和喚醒方法時(shí),我們會(huì)聯(lián)想到另一組喚醒方法wait()和notify(),這兩組方法還是有所區(qū)別的。

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

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

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();
    }
}

那如果我們先通過(guò)線程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é)果來(lái)看,雖然線程B先喚醒了線程A,然后線程A再開(kāi)始阻塞,但是線程A還是處于喚醒狀態(tài),這是為什么呢?

接下來(lái)我找了段LockSupport類(lèi)中的注釋?zhuān)鋵?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.)

這段話大意是說(shuō),LockSupport類(lèi)使用permits這個(gè)東西來(lái)實(shí)現(xiàn)線程的阻塞和喚醒。每一個(gè)線程都會(huì)使用到(擁有)permit,且permit的值默認(rèn)為0。接著它又說(shuō),這個(gè)概念和Semaphore信號(hào)量差不多,但是permit的值只有0和1兩個(gè)值。哦~原來(lái)是這樣。

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

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

相關(guān)文章

  • SpringBoot定義過(guò)濾器、監(jiān)聽(tīng)器、攔截器的方法

    SpringBoot定義過(guò)濾器、監(jiān)聽(tīng)器、攔截器的方法

    本篇文章主要介紹了SpringBoot定義過(guò)濾器、監(jiān)聽(tīng)器、攔截器的方法,具有一定的參考價(jià)值,有興趣的可以了解一下。
    2017-04-04
  • SpringCloud遠(yuǎn)程服務(wù)調(diào)用實(shí)戰(zhàn)筆記

    SpringCloud遠(yuǎn)程服務(wù)調(diào)用實(shí)戰(zhàn)筆記

    本文給大家介紹SpringCloud遠(yuǎn)程服務(wù)調(diào)用實(shí)戰(zhàn)筆記,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2021-11-11
  • Java數(shù)據(jù)結(jié)構(gòu)之簡(jiǎn)單的連接點(diǎn)(link)實(shí)現(xiàn)方法示例

    Java數(shù)據(jù)結(jié)構(gòu)之簡(jiǎn)單的連接點(diǎn)(link)實(shí)現(xiàn)方法示例

    這篇文章主要介紹了Java數(shù)據(jù)結(jié)構(gòu)之簡(jiǎn)單的連接點(diǎn)(link)實(shí)現(xiàn)方法,涉及java指針指向節(jié)點(diǎn)的相關(guān)使用技巧,需要的朋友可以參考下
    2017-10-10
  • springboot+thymeleaf國(guó)際化之LocaleResolver接口的示例

    springboot+thymeleaf國(guó)際化之LocaleResolver接口的示例

    本篇文章主要介紹了springboot+thymeleaf國(guó)際化之LocaleResolver的示例 ,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-11-11
  • Spring?Boot實(shí)現(xiàn)web.xml功能示例詳解

    Spring?Boot實(shí)現(xiàn)web.xml功能示例詳解

    這篇文章主要介紹了Spring?Boot實(shí)現(xiàn)web.xml功能,通過(guò)本文介紹我們了解到,在Spring Boot應(yīng)用中,我們可以通過(guò)注解和編程兩種方式實(shí)現(xiàn)web.xml的功能,包括如何創(chuàng)建及注冊(cè)Servlet、Filter以及Listener等,需要的朋友可以參考下
    2023-09-09
  • Java中List集合數(shù)據(jù)修改方式

    Java中List集合數(shù)據(jù)修改方式

    這篇文章主要介紹了Java中List集合數(shù)據(jù)修改方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • Java8中Stream使用的一個(gè)注意事項(xiàng)

    Java8中Stream使用的一個(gè)注意事項(xiàng)

    最近在工作中發(fā)現(xiàn)了對(duì)于集合操作轉(zhuǎn)換的神器,java8新特性 stream,但在使用中遇到了一個(gè)非常重要的注意點(diǎn),所以這篇文章主要給大家介紹了關(guān)于Java8中Stream使用過(guò)程中的一個(gè)注意事項(xiàng),需要的朋友可以參考借鑒,下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-11-11
  • springboot配置允許循環(huán)依賴(lài)問(wèn)題

    springboot配置允許循環(huán)依賴(lài)問(wèn)題

    這篇文章主要介紹了springboot配置允許循環(huán)依賴(lài)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • Java字節(jié)與字符流永久存儲(chǔ)json數(shù)據(jù)

    Java字節(jié)與字符流永久存儲(chǔ)json數(shù)據(jù)

    本篇文章給大家詳細(xì)講述了Java字節(jié)與字符流永久存儲(chǔ)json數(shù)據(jù)的方法,以及代碼分享,有興趣的參考學(xué)習(xí)下。
    2018-02-02
  • Java+swing實(shí)現(xiàn)經(jīng)典貪吃蛇游戲

    Java+swing實(shí)現(xiàn)經(jīng)典貪吃蛇游戲

    貪吃蛇(也叫做貪食蛇)游戲是一款休閑益智類(lèi)游戲,有PC和手機(jī)等多平臺(tái)版本。既簡(jiǎn)單又耐玩。本文將通過(guò)java的swing來(lái)實(shí)現(xiàn)這一游戲,需要的可以參考一下
    2022-01-01

最新評(píng)論