91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

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

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

Java并發之Condition的示例分析

發布時間:2021-09-01 14:43:31 來源:億速云 閱讀:135 作者:小新 欄目:開發技術

這篇文章主要介紹了Java并發之Condition的示例分析,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

    在使用Lock之前,我們使用的最多的同步方式應該是synchronized關鍵字來實現同步方式了。配合Object的wait()、notify()系列方法可以實現等待/通知模式。Condition接口也提供了類似Object的監視器方法,與Lock配合可以實現等待/通知模式,但是這兩者在使用方式以及功能特性上還是有差別的。Object和Condition接口的一些對比。摘自《Java并發編程的藝術》

    Java并發之Condition的示例分析

    一、Condition接口介紹和示例

            首先我們需要明白condition對象是依賴于lock對象的,意思就是說condition對象需要通過lock對象進行創建出來(調用Lock對象的newCondition()方法)。consition的使用方式非常的簡單。但是需要注意在調用方法前獲取鎖。

    package com.ydl.test.juc;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class ConditionUseCase {
    
        public Lock lock = new ReentrantLock();
        public Condition condition = lock.newCondition();
    
        public static void main(String[] args)  {
            ConditionUseCase useCase = new ConditionUseCase();
            ExecutorService executorService = Executors.newFixedThreadPool (2);
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    useCase.conditionWait();
                }
            });
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    useCase.conditionSignal();
                }
            });
        }
    
        public void conditionWait()  {
            lock.lock();
            try {
                System.out.println(Thread.currentThread().getName() + "拿到鎖了");
                System.out.println(Thread.currentThread().getName() + "等待信號");
                condition.await();
                System.out.println(Thread.currentThread().getName() + "拿到信號");
            }catch (Exception e){
    
            }finally {
                lock.unlock();
            }
        }
        public void conditionSignal() {
            lock.lock();
            try {
                Thread.sleep(5000);
                System.out.println(Thread.currentThread().getName() + "拿到鎖了");
                condition.signal();
                System.out.println(Thread.currentThread().getName() + "發出信號");
            }catch (Exception e){
    
            }finally {
                lock.unlock();
            }
        }
    
    }

    1 pool-1-thread-1拿到鎖了

    2 pool-1-thread-1等待信號
    3 pool-1-thread-2拿到鎖了
    4 pool-1-thread-2發出信號 

    如示例所示,一般都會將Condition對象作為成員變量。當調用await()方法后,當前線程會釋放鎖并在此等待,而其他線程調用Condition對象的signal()方法,通知當前線程后,當前線程才從await()方法返回,并且在返回前已經獲取了鎖。

    二、Condition接口常用方法

            condition可以通俗的理解為條件隊列。當一個線程在調用了await方法以后,直到線程等待的某個條件為真的時候才會被喚醒。這種方式為線程提供了更加簡單的等待/通知模式。Condition必須要配合鎖一起使用,因為對共享狀態變量的訪問發生在多線程環境下。一個Condition的實例必須與一個Lock綁定,因此Condition一般都是作為Lock的內部實現。

    1. await() :造成當前線程在接到信號或被中斷之前一直處于等待狀態。

    2. await(long time, TimeUnit unit) :造成當前線程在接到信號、被中斷或到達指定等待時間之前一直處于等待狀態。

    3. awaitNanos(long nanosTimeout) :造成當前線程在接到信號、被中斷或到達指定等待時間之前一直處于等待狀態。返回值表示剩余時間,如果在nanosTimesout之前喚醒,那么返回值 = nanosTimeout - 消耗時間,如果返回值 <= 0 ,則可以認定它已經超時了。

    4. awaitUninterruptibly() :造成當前線程在接到信號之前一直處于等待狀態。【注意:該方法對中斷不敏感】。

    5. awaitUntil(Date deadline) :造成當前線程在接到信號、被中斷或到達指定最后期限之前一直處于等待狀態。如果沒有到指定時間就被通知,則返回true,否則表示到了指定時間,返回返回false。

    6. signal() :喚醒一個等待線程。該線程從等待方法返回前必須獲得與Condition相關的鎖。

    7. signal()All :喚醒所有等待線程。能夠從等待方法返回的線程必須獲得與Condition相關的鎖。

    三、Condition接口原理簡單解析

            Condition是AQS的內部類。每個Condition對象都包含一個隊列(等待隊列)。等待隊列是一個FIFO的隊列,在隊列中的每個節點都包含了一個線程引用,該線程就是在Condition對象上等待的線程,如果一個線程調用了Condition.await()方法,那么該線程將會釋放鎖、構造成節點加入等待隊列并進入等待狀態。等待隊列的基本結構如下所示。

    Java并發之Condition的示例分析

    等待分為首節點和尾節點。當一個線程調用Condition.await()方法,將會以當前線程構造節點,并將節點從尾部加入等待隊列。新增節點就是將尾部節點指向新增的節點。節點引用更新本來就是在獲取鎖以后的操作,所以不需要CAS保證。同時也是線程安全的操作。

    3.1、等待

    當線程調用了await方法以后。線程就作為隊列中的一個節點被加入到等待隊列中去了。同時會釋放鎖的擁有。當從await方法返回的時候。一定會獲取condition相關聯的鎖。當等待隊列中的節點被喚醒的時候,則喚醒節點的線程開始嘗試獲取同步狀態。如果不是通過 其他線程調用Condition.signal()方法喚醒,而是對等待線程進行中斷,則會拋出InterruptedException異常信息。

    3.2、通知

    調用Condition的signal()方法,將會喚醒在等待隊列中等待最長時間的節點(條件隊列里的首節點),在喚醒節點前,會將節點移到同步隊列中。當前線程加入到等待隊列中如圖所示:

    Java并發之Condition的示例分析

    在調用signal()方法之前必須先判斷是否獲取到了鎖。接著獲取等待隊列的首節點,將其移動到同步隊列并且利用LockSupport喚醒節點中的線程。節點從等待隊列移動到同步隊列如下圖所示:

    Java并發之Condition的示例分析

    被喚醒的線程將從await方法中的while循環中退出。隨后加入到同步狀態的競爭當中去。成功獲取到競爭的線程則會返回到await方法之前的狀態。

    四、總結

    調用await方法后,將當前線程加入Condition等待隊列中。當前線程釋放鎖。否則別的線程就無法拿到鎖而發生死鎖。自旋(while)掛起,不斷檢測節點是否在同步隊列中了,如果是則嘗試獲取鎖,否則掛起。當線程被signal方法喚醒,被喚醒的線程將從await()方法中的while循環中退出來,然后調用acquireQueued()方法競爭同步狀態。

    五、利用Condition實現生產者消費者模式

    import java.util.LinkedList;
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class BoundedQueue {
    
        private LinkedList<Object> buffer;    //生產者容器
        private int maxSize ;           //容器最大值是多少
        private Lock lock;
        private Condition fullCondition;
        private Condition notFullCondition;
        BoundedQueue(int maxSize){
            this.maxSize = maxSize;
            buffer = new LinkedList<Object>();
            lock = new ReentrantLock();
            fullCondition = lock.newCondition();
            notFullCondition = lock.newCondition();
        }
    
        /**
         * 生產者
         * @param obj
         * @throws InterruptedException
         */
        public void put(Object obj) throws InterruptedException {
            lock.lock();    //獲取鎖
            try {
                while (maxSize == buffer.size()){
                    notFullCondition.await();       //滿了,添加的線程進入等待狀態
                }
                buffer.add(obj);
                fullCondition.signal(); //通知
            } finally {
                lock.unlock();
            }
        }
    
        /**
         * 消費者
         * @return
         * @throws InterruptedException
         */
        public Object get() throws InterruptedException {
            Object obj;
            lock.lock();
            try {
                while (buffer.size() == 0){ //隊列中沒有數據了 線程進入等待狀態
                    fullCondition.await();
                }
                obj = buffer.poll();
                notFullCondition.signal(); //通知
            } finally {
                lock.unlock();
            }
            return obj;
        }
    
    }

    感謝你能夠認真閱讀完這篇文章,希望小編分享的“Java并發之Condition的示例分析”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!

    向AI問一下細節

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

    AI

    宣汉县| 兴和县| 彭州市| 乌拉特中旗| 通化县| 浑源县| 平乡县| 岢岚县| 扎鲁特旗| 巴林左旗| 尚义县| 沁阳市| 石河子市| 湘阴县| 静宁县| 长丰县| 府谷县| 昌江| 西平县| 德钦县| 永德县| 尉犁县| 定兴县| 秀山| 青铜峡市| 论坛| 拜城县| 南充市| 万安县| 淳安县| 抚顺市| 广平县| 荃湾区| 自贡市| 鸡西市| 宝清县| 正宁县| 嘉荫县| 涪陵区| 宜兰市| 垣曲县|