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

溫馨提示×

溫馨提示×

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

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

Java的LockSupport工具類如何使用

發布時間:2022-02-21 16:39:42 來源:億速云 閱讀:104 作者:iii 欄目:開發技術

本文小編為大家詳細介紹“Java的LockSupport工具類如何使用”,內容詳細,步驟清晰,細節處理妥當,希望這篇“Java的LockSupport工具類如何使用”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。

    LockSupport類

    用于創建鎖和其他同步類的基本線程阻塞原語,此類與使用它的每個線程關聯一個許可。如果獲得許可,將立即返回對park的調用,并在此過程中消耗掉它;否則may會被阻止。調用unpark可使許可證可用(如果尚不可用)。(不過與信號量不同,許可證不會累積。最多只能有一個。)
    方法park和unpark提供了有效的阻塞和解阻塞線程的方法,這些線程不會遇到導致已棄用的方法Thread.suspend和Thread.resume無法用于以下問題:由于許可,在調用park的一個線程與試圖進行unpark的另一個線程之間的競爭將保留生命力。此外,如果調用者的線程被中斷并且支持超時版本,則park將返回。 park方法也可能在其他任何時間出于“無理由”返回,因此通常必須在循環中調用該循環,該循環在返回時會重新檢查條件。從這個意義上說,park是對“繁忙等待”的優化,它不會浪費太多的時間,而必須與unpark配對才能生效。
    了解了其作用,我們看看相關API。

    LockSupport.park()

    park():除非有許可,否則出于線程調度目的禁用當前線程。
    如果許可證可用,則將其消耗掉,并立即返回呼叫;否則,將立即返回該呼叫。出于線程調度的目的,當前線程將被禁用,并處于休眠狀態,直到發生以下三種情況之一:
    1.其他一些線程以當前線程為目標調用unpark()方法
    2.其他一些線程Threadinterrupt interrupts當前線程
    3.虛假地調用返回
    源碼:

    public static void park() {
        UNSAFE.park(false, 0L);
    }

    LockSupport都是調用的UNSAFE的方法,我們先看看park方法

    public class LockSupportMain {
        public static void main(String[] args) {
            System.out.println("begin park!");
            LockSupport.park();
            System.out.println("end park!");
        }
    }

    我們調用了park方法,導致Main線程一直被阻塞,一直沒有結束,因為默認的情況下,調用線程是不持有許可證的,我們如何解決呢?上面提到過三個方式,我們一個一個的驗證。

    1.調用unpack方法獲得許可

    unpack():如果給定線程尚不可用,則使它可用。如果線程在park上被阻止,則它將取消阻止。否則,將確保其對park的下一次調用不會阻塞。如果給定線程尚未啟動,則不能保證此操作完全無效。
    源碼:

    public static void unpark(Thread thread) {
        if (thread != null)
            UNSAFE.unpark(thread);
    }
    public class LockSupportMain2 {
        public static void main(String[] args) {
            System.out.println("begin park!");
            LockSupport.unpark(Thread.currentThread());
            LockSupport.park();
            System.out.println("end park!");
        }
    }

    可以看出,當前的線程main已經釋放了,沒有進行阻塞,直接運行完成了。
    我們創建一個線程有Main線程進行unpark方法將線程在阻塞的情況下,進行運行。

    public class LockSupportMain3 {
    
        public static void main(String[] args) throws InterruptedException {
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    System.out.println("begin start thread name: " + Thread.currentThread().getName() + " park");
                    LockSupport.park();
                    System.out.println("end start thread name: " + Thread.currentThread().getName() + " park");
                }
            };
    
            Thread thread = new Thread(runnable);
            thread.start();
            Thread.sleep(2000);
            System.out.println("main thread call unpark");
            LockSupport.unpark(thread);
        }
    
    }

    運行結果可以看出,其他一些線程以當前線程為目標調用unpark()方法可以將線程的park導致阻塞的繼續運行。

    2.調用中斷interrupts方法獲得許可

    由于park方法不會告訴你何種原因返回,所以調用者需要根據之前調用park方法的原因,再次檢查條件是否滿足,如果不能滿足,就還需要調用park方法

    public class LockSupportMain4 {
    
        public static void main(String[] args) throws InterruptedException {
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    System.out.println("begin start thread name: " + Thread.currentThread().getName() + " park");
                    while (!Thread.currentThread().isInterrupted()) {
                        LockSupport.park();
                    }
                    System.out.println("end start thread name: " + Thread.currentThread().getName() + " park");
                }
            };
    
            Thread thread = new Thread(runnable);
            thread.start();
            Thread.sleep(2000);
            //通過interrupt方法 讓park阻塞繼續運行
            thread.interrupt();
        }
    
    }

    由運行可以看出,其他一些線程Threadinterrupt interrupts當前線程是可以將park阻塞的線程繼續運行。

    parkNanos(long nanos)

    parkNanos(long nanos):除非允許使用許可,否則在指定的等待時間內禁用用于線程調度的當前線程。
    源碼:

    public static void parkNanos(long nanos) {
        if (nanos > 0)
            UNSAFE.park(false, nanos);
    }
    public class LockSupportMain5 {
    
        public static void main(String[] args) throws InterruptedException {
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    System.out.println("begin start thread name: " + Thread.currentThread().getName() + " park");
                    LockSupport.parkNanos(3_000_000_000L);
                    System.out.println("end start thread name: " + Thread.currentThread().getName() + " park");
                }
            };
            Thread thread = new Thread(runnable);
            thread.start();
        }
    }

    三秒之后,阻塞三秒之后繼續運行。

    park(Object blocker)

    park(Object blocker):除非有許可,否則出于線程調度目的禁用當前線程
    源碼:

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

    這里的blocker對象是Thread類中的blocker對象,代碼如下:

    //提供給java.util.concurrent.locks.LockSupport.park的當前調用的參數。
    //由(私有)java.util.concurrent.locks.LockSupport.setBlocker設置使用
    //java.util.concurrent.locks.LockSupport.getBlocker進行訪問
    volatile Object parkBlocker;

    parkNanos(Object blocker, long 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);
        }
    }

    parkUntil(Object blocker, long deadline)

    parkUntil(Object blocker, long deadline):除非指定許可,否則禁用當前線程以進行線程調度,直到指定的期限。
    源碼:

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

    我們使用java API中的例子看看:

    public class LockSupportMain6 {
        private final AtomicBoolean locked = new AtomicBoolean(false);
        private final Queue<Thread> waiters
                = new ConcurrentLinkedQueue<Thread>();
    
        public void lock() {
            boolean wasInterrupted = false;
            Thread current = Thread.currentThread();
            waiters.add(current);
    
            // 不在隊列中時先阻塞或無法獲取鎖定
            while (waiters.peek() != current ||
                    !locked.compareAndSet(false, true)) {
                LockSupport.park(this);
                // 等待時忽略中斷 如果park方法是因為被中斷而返回,則忽略中斷,并且重新設置中斷標記,做個標記
                if (Thread.interrupted()) {
                    wasInterrupted = true;
                }
            }
            waiters.remove();
            // 退出時重新聲明中斷狀態
            if (wasInterrupted)          
            {
                current.interrupt();
            }
        }
        public void unlock() {
            locked.set(false);
            LockSupport.unpark(waiters.peek());
        }
    }

    有blocker的可以傳遞給開發人員更多的現場信息,可以查看到當前線程的阻塞對象,方便定位問題

    讀到這里,這篇“Java的LockSupport工具類如何使用”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。

    向AI問一下細節

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

    AI

    博客| 二连浩特市| 江源县| 肃北| 保亭| 广河县| 行唐县| 女性| 永平县| 墨江| 抚顺市| 浙江省| 肇州县| 宽甸| 沅陵县| 思茅市| 威远县| 锦屏县| 玉林市| 苏尼特右旗| 改则县| 凭祥市| 鹤岗市| 南宫市| 古蔺县| 鄂托克前旗| 镇赉县| 双流县| 榆社县| 宜昌市| 日照市| 吉木乃县| 团风县| 丰顺县| 三穗县| 宁乡县| 炉霍县| 桃园市| 吉木乃县| 浦北县| 泰安市|