java condition使用及分析__java

來源:互聯網
上載者:User

背景:

    上一篇文章基於object的wait、notify實現了生產者、消費者模式。本篇文章繼續梳理Condition。 condition 介紹及demo

 Condition是在java 1.5中才出現的,它用來替代傳統的Object的wait()、notify()實現線程間的協作,相比使用Object的wait()、notify(),使用Condition的await()、signal()這種方式實現線程間協作更加安全和高效。因此通常來說比較推薦使用Condition,阻塞隊列實際上是使用了Condition來類比線程間協作。 Condition是個介面,基本的方法就是await()和signal()方法; Condition依賴於Lock介面,產生一個Condition的基本代碼是lock.newCondition()   調用Condition的await()和signal()方法,都必須在lock保護之內,就是說必須在lock.lock()和lock.unlock之間才可以使用

  Conditon中的await()對應Object的wait();

  Condition中的signal()對應Object的notify();

Condition中的signalAll()對應Object的notifyAll()。

下面是demo:  

package thread;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;/** *  * @author zhangliang * * 2016年4月8日 下午5:48:54 */public class ConTest { final Lock lock = new ReentrantLock(); final Condition condition = lock.newCondition();public static void main(String[] args) {// TODO Auto-generated method stubConTest test = new ConTest();    Producer producer = test.new Producer();    Consumer consumer = test.new Consumer();                  consumer.start();     producer.start();} class Consumer extends Thread{                 @Override        public void run() {            consume();        }                  private void consume() {                                        try {                   lock.lock();                    System.out.println("我在等一個新訊號"+this.currentThread().getName());                    condition.await();                                    } catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();} finally{System.out.println("拿到一個訊號"+this.currentThread().getName());                    lock.unlock();                }                    }    }  class Producer extends Thread{                 @Override        public void run() {            produce();        }                  private void produce() {                             try {                   lock.lock();                       System.out.println("我拿到鎖"+this.currentThread().getName());                        condition.signalAll();                                             System.out.println("我發出了一個訊號:"+this.currentThread().getName());                } finally{                    lock.unlock();                }            } }    }
運行結果:


Condition的執行方式,是當線上程Consumer中調用await方法後,線程Consumer將釋放鎖,並且將自己沉睡,等待喚醒,線程Producer擷取到鎖後,開始做事,完畢後,調用Condition的signalall方法,喚醒線程Consumer,線程Consumer恢複執行。

以上說明Condition是一個多線程間協調通訊的工具類,使得某個,或者某些線程一起等待某個條件(Condition),只有當該條件具備( signal 或者 signalAll方法被帶調用)時 ,這些等待線程才會被喚醒,從而重新爭奪鎖。 Condition實現生產者、消費者模式:

package thread;import java.util.PriorityQueue;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class ConTest2 {    private int queueSize = 10;    private PriorityQueue<Integer> queue = new PriorityQueue<Integer>(queueSize);    private Lock lock = new ReentrantLock();    private Condition notFull = lock.newCondition();    private Condition notEmpty = lock.newCondition();         public static void main(String[] args) throws InterruptedException  {    ConTest2 test = new ConTest2();        Producer producer = test.new Producer();        Consumer consumer = test.new Consumer();                  producer.start();        consumer.start();        Thread.sleep(0);        producer.interrupt();        consumer.interrupt();    }          class Consumer extends Thread{                  @Override        public void run() {            consume();        }        volatile boolean flag=true;          private void consume() {            while(flag){                lock.lock();                try {                    while(queue.isEmpty()){                        try {                            System.out.println("隊列空,等待資料");                            notEmpty.await();                        } catch (InterruptedException e) {                                                      flag =false;                        }                    }                    queue.poll();                //每次移走隊首元素                    notFull.signal();                    System.out.println("從隊列取走一個元素,隊列剩餘"+queue.size()+"個元素");                } finally{                    lock.unlock();                }            }        }    }          class Producer extends Thread{                  @Override        public void run() {            produce();        }        volatile boolean flag=true;          private void produce() {            while(flag){                lock.lock();                try {                    while(queue.size() == queueSize){                        try {                            System.out.println("隊列滿,等待有空餘空間");                            notFull.await();                        } catch (InterruptedException e) {                                                        flag =false;                        }                    }                    queue.offer(1);        //每次插入一個元素                    notEmpty.signal();                    System.out.println("向隊列取中插入一個元素,隊列剩餘空間:"+(queueSize-queue.size()));                } finally{                    lock.unlock();                }            }        }    }}
運行結果如下:


condition實現分析:
Condition介面包含了多種await方式和兩個通知方法 ConditionObject實現了Condition介面,是AbstractQueuedSynchronizer的內部類 Reentrantlock的newCondition方法返回與某個lock執行個體相關的Condition對象

public abstract class AbstractQueuedLongSynchronizer    extends AbstractOwnableSynchronizer    implements java.io.Serializable {

 
<span style="font-size:18px;">結合上面的類圖,我們看到condition實現是依賴於aqs,而aqs是個抽象類別。裡面定義了同步器的基本架構,實現了基本的結構功能。只留有狀態條件的維護由具體同步器根據具體情境來定製,如常見的 ReentrantLock 、 RetrantReadWriteLock和CountDownLatch 等等,AQS內容太多,盡量只簡明梳理condition相關流程,不太深入理解底層源碼。</span>

下面結合上面demo來分析流程。 reentrantLock.newCondition() 返回的是Condition的一個實現,該類在AbstractQueuedSynchronizer(AQS)中被實現,叫做newCondition()

    public Condition newCondition() {        return sync.newCondition();    }
我們看一下這個await的方法,它是AQS的方法,


public final void await() throws InterruptedException {
02 if (Thread.interrupted())
03  throw new InterruptedException();
04  Node node = addConditionWaiter(); //將當前線程封裝下後,
05                                    //添加到Condition自己維護的一個鏈表中。
06 int savedState = fullyRelease(node);//釋放當前線程佔有的鎖,從demo中看到,
07                                        //調用await前,當前線程是佔有鎖的
08  
09 int interruptMode = 0;

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.