亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

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

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

線程阻塞喚醒工具LockSupport怎么使用

發布時間:2023-01-28 15:38:02 來源:億速云 閱讀:147 作者:iii 欄目:開發技術

本篇內容主要講解“線程阻塞喚醒工具LockSupport怎么使用”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“線程阻塞喚醒工具LockSupport怎么使用”吧!

    LockSupport 簡介

    LockSupport 是 Java 并發編程中一個非常重要的組件,我們熟知的并發組件 Lock、線程池、CountDownLatch 等都是基于 AQS 實現的,而 AQS 內部控制線程阻塞和喚醒又是通過 LockSupport 來實現的。

    從該類的注釋上也可以發現,它是一個控制線程阻塞和喚醒的工具,與以往的不同是它解決了曾經 wait()、notify()、await()、signal() 的局限。

    回顧 synchronized 和 Lock

    我們知道 Java 中實現并發安全通常會通過這兩種加鎖的方式,對于 synchronized 加鎖的方式,如果我們想要控制線程的阻塞和喚醒是通過鎖對象的 wait()notify() 方法,以下面循環交替打印 AB 為例

    int status = 2;
    public static void main(String[] args) throws InterruptedException {
        TestSync obj = new TestSync();
         new Thread(() -> {
            synchronized (obj){
                while (true){
                    if(obj.status == 1){
                        obj.wait();
                    }
                    System.out.println("A");
                    obj.status = 1;
                    TimeUnit.SECONDS.sleep(1);
                    obj.notify();
                }
            }
         }).start();
        new Thread(() -> {
           synchronized (obj){
              while (true){
                  if(obj.status == 2){
                      obj.wait();
                  }
                  System.out.println("B");
                  obj.status = 2;
                  TimeUnit.SECONDS.sleep(1);
                  obj.notify();
              }
           }
        }).start();
    }

    如果我們使用 Lock 實現類,上述代碼幾乎是一樣的,只是先獲取 Condition 對象

     Condition condition = lock.newCondition();

    obj.wait() 換成 condition.await()obj.notify() 換成 condition.signal() 即可。

    LockSupport 和 synchronized 和 Lock 的阻塞方式對比

    技術阻塞喚醒方式局限
    synchronized使用鎖對象的 wait()、notify()1. 只能用在 synchronized 包裹的同步代碼塊中 2. 必須先 wait() 才能 notify()
    Lock使用 condition 的 await()、signal()1. 只能用在 lock 鎖住的代碼塊中 2. 必須先 await() 才能 signal()
    LockSupportpark()、unpark(Thread t)沒有限制

    LockSupport 的使用

    下面代碼中,我們使用 LockSupport 去阻塞和喚醒線程,我們可以多次嘗試,LockSupportpark()unpark() 方法沒有先后順序的限制,也不需要捕獲異常,也沒有限制要在什么代碼塊中才能使用。

        public static void main(String[] args) throws InterruptedException {
            Thread t1 = new Thread(() -> {
                System.out.println("A");
                LockSupport.park();
                System.out.println("被喚醒");
            });
            t1.start();
            TimeUnit.SECONDS.sleep(2);
            new Thread(() -> {
                System.out.println("B");
                LockSupport.unpark(t1);
            }).start();
        }

    LockSupport 注意事項

    許可證提前發放

    從該類的注釋中我們可以看到這個類存儲了使用它的線程的一個許可證,當調用 park() 方法的時候會判斷當前線程的許可證是否存在,如果存在將直接放行,否則就阻塞。

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("A");
            LockSupport.park();//不會阻塞
            System.out.println("被喚醒");
        });
        t1.start();
        TimeUnit.SECONDS.sleep(2);
        new Thread(() -> {
            System.out.println("B");
            System.out.println("先調用 unpark()");
            LockSupport.unpark(t1);
        },"t2").start();
    }

    看這個代碼示例,這里我們在 t2 中先讓線程 t1 unpark(), 然后在 t1 中調用 park(), 結果并不會阻塞 t1 線程。因為在 t2 中調用 LockSupport.unpark(t1); 的時候相當于給 t1 提前準備好了許可證。

    許可證不會累計

    LockSupport.unpark(t1); 無論調用多少次,t1 的通行證只有一個,當在 t1 中調用兩次 park() 方法時線程依然會被阻塞。

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("A");
            LockSupport.park();
            LockSupport.park();
            System.out.println("被喚醒");
        });
        t1.start();
        TimeUnit.SECONDS.sleep(2);
        new Thread(() -> {
            System.out.println("B");
            System.out.println("先調用 unpark()");
            LockSupport.unpark(t1);
            LockSupport.unpark(t1);
            LockSupport.unpark(t1);
            LockSupport.unpark(t1);
            LockSupport.unpark(t1);
        },"t2").start();
    }

    以上述代碼為例,t1 將被阻塞。

    LockSupport 底層實現

    觀察源碼發現 park() 和 unpark() 最底下調用的是 native() 方法,源碼在 C++ 中實現

    @IntrinsicCandidate
    public native void park(boolean isAbsolute, long time);
    @IntrinsicCandidate
    public native void unpark(Object thread);

    到此,相信大家對“線程阻塞喚醒工具LockSupport怎么使用”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

    向AI問一下細節

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

    AI

    达孜县| 腾冲县| 斗六市| 本溪市| 来宾市| 哈巴河县| 中宁县| 浦北县| 九江县| 诏安县| 申扎县| 建德市| 荔波县| 务川| 鄢陵县| 榆中县| 万山特区| 黄大仙区| 罗源县| 安顺市| 宜兰县| 嘉义市| 涟水县| 嘉祥县| 宜昌市| 栾川县| 武城县| 建昌县| 台南县| 隆化县| 申扎县| 曲阜市| 临猗县| 仁化县| 营口市| 改则县| 铜山县| 张家界市| 昔阳县| 枣庄市| 吉首市|