日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

解析java中的condition

瀏覽:164日期:2022-08-10 17:55:57
目錄一、condition 介紹及demo二、Condition接口     三、condition實現分析3.1、等待隊列3.2、等待3.3、通知一、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()。

解析java中的condition

condition常見例子arrayblockingqueue。下面是demo:

package thread; import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;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{ @Overridepublic 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{ @Overridepublic 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();} } } }

運行結果:

解析java中的condition

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

運行結果如下:

解析java中的condition

二、Condition接口     

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

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

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

awaitNanos(long nanosTimeout) :造成當前線程在接到信號、被中斷或到達指定等待時間之前一直處于等待狀態。

返回值表示剩余時間,如果在nanosTimesout之前喚醒,那么返回值 = nanosTimeout - 消耗時間,如果返回值 <= 0 ,則可以認定它已經超時了。

awaitUninterruptibly() :造成當前線程在接到信號之前一直處于等待狀態?!咀⒁猓涸摲椒▽χ袛嗖幻舾小?。

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

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

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

三、condition實現分析

解析java中的condition

Condition接口包含了多種await方式和兩個通知方法 ConditionObject實現了Condition接口,是AbstractQueuedSynchronizer的內部類(因為Condition的操作都需要獲取想關聯的鎖) Reentrantlock的newCondition方法返回與某個lock實例相關的Condition對象

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

結合上面的類圖,我們看到condition實現是依賴于aqs,而aqs是個抽象類。里面定義了同步器的基本框架,實現了基本的結構功能。只留有狀態條件的維護由具體同步器根據具體場景來定制,如常見的 ReentrantLock 、 RetrantReadWriteLock和CountDownLatch 等等,

3.1、等待隊列

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

解析java中的condition

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

public class ConditionObject implements Condition, java.io.Serializable { private static final long serialVersionUID = 1173984872572414699L; /** First node of condition queue. */ private transient Node firstWaiter; /** Last node of condition queue. */ private transient Node lastWaiter;3.2、等待

 當線程調用了Condition的await()方法以后。線程就作為隊列中的一個節點被加入到等待隊列中去了。同時會釋放鎖的擁有。當從await方法返回的時候。當前線程一定會獲取condition相關聯的鎖。

如果從隊列(同步隊列和等待隊列)的角度去看await()方法,當調用await()方法時,相當于同步隊列的首節點(獲取鎖的節點)移動到Condition的等待隊列中。

調用該方法的線程成功的獲取鎖的線程,也就是同步隊列的首節點,該方法會將當前線程構造成節點并加入到等待隊列中,然后釋放同步狀態,喚醒同步隊列中的后繼節點,然后當前線程會進入等待狀態。

當等待隊列中的節點被喚醒的時候,則喚醒節點的線程開始嘗試獲取同步狀態。如果不是通過 其他線程調用Condition.signal()方法喚醒,而是對等待線程進行中斷,則會拋出InterruptedException異常信息。

   解析java中的condition

我們看一下這個await的方法,它是AQS的方法,

public final void await() throws InterruptedException { if (Thread.interrupted())  throw new InterruptedException();  Node node = addConditionWaiter(); //將當前線程包裝下后,    //添加到Condition自己維護的一個鏈表中。 int savedState = fullyRelease(node);//釋放當前線程占有的鎖,從demo中看到,    //調用await前,當前線程是占有鎖的 int interruptMode = 0;  while (!isOnSyncQueue(node)) {//釋放完畢后,遍歷AQS的隊列,看當前節點是否在隊列中,//不在 說明它還沒有競爭鎖的資格,所以繼續將自己沉睡。//直到它被加入到隊列中,聰明的你可能猜到了,//沒有錯,在singal的時候加入不就可以了? LockSupport.park(this); if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)   break;  } //被喚醒后,重新開始正式競爭鎖,同樣,如果競爭不到還是會將自己沉睡,等待喚醒重新開始競爭。if (acquireQueued(node, savedState) && interruptMode != THROW_IE) interruptMode = REINTERRUPT;if (node.nextWaiter != null) unlinkCancelledWaiters();if (interruptMode != 0) reportInterruptAfterWait(interruptMode);}

結合代碼去看,同步隊列的首節點 并不會直接加入等待隊列,而是通過addConditionWaiter把當前線程構造成一個新節點并加入到等待隊列中。

/** * Adds a new waiter to wait queue. * @return its new wait node */private Node addConditionWaiter() { Node t = lastWaiter; // If lastWaiter is cancelled, clean out. if (t != null && t.waitStatus != Node.CONDITION) {unlinkCancelledWaiters();t = lastWaiter; } Node node = new Node(Thread.currentThread(), Node.CONDITION); if (t == null)firstWaiter = node; elset.nextWaiter = node; lastWaiter = node; return node;}3.3、通知

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

解析java中的condition

回到上面的demo,鎖被釋放后,線程Consumer開始沉睡,這個時候線程因為線程Consumer沉睡時,會喚醒AQS隊列中的頭結點,所所以線程Producer會開始競爭鎖,并獲取到,執行完后線程Producer會調用signal方法,“發出”signal信號,signal方法如下:

public final void signal() { if (!isHeldExclusively())  throw new IllegalMonitorStateException(); Node first = firstWaiter; //firstWaiter為condition自己維護的一個鏈表的頭結點, //取出第一個節點后開始喚醒操作 if (first != null)  doSignal(first);}

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

被喚醒的線程將從await方法中的while循環中退出(  while (!isOnSyncQueue(node)) { 方法返回true,節點已經在同步隊列中)。隨后調用同步器的acquireQueued()方法加入到同步狀態的競爭當中去。成功獲取到競爭的線程從先前調用await方法返回,此時該線程已經成功獲取了鎖。

*********************************************

AQS的同步隊列與Condition的等待隊列,兩個隊列的作用是不同,事實上,每個線程也僅僅會同時存在以上兩個隊列中的一個,流程是這樣的:

解析java中的condition

注意:

1.線程producer調用signal方法,這個時候Condition的等待隊列中只有線程Consumer一個節點,于是它被取出來,并被加入到AQS的等待隊列中。  注意,這個時候,線程Consumer 并沒有被喚醒。

2.Sync是AQS的抽象子類,實現可重入和互斥的大部分功能。在Sync的子類中有FairSync和NonfairSync兩種代表公平鎖策略和非公平鎖策略。Sync lock方法留給子類去實現,NonfairSync的實現:

final void lock() { if (compareAndSetState(0, 1))setExclusiveOwnerThread(Thread.currentThread()); elseacquire(1);}

其中如果一開始獲取鎖成功,是直接設置當前線程。

否則執行acquire(1),也就是進入aqs等待隊列。這里不展開細節。

可以這樣理解,整個協作過程是靠結點在AQS的等待隊列和Condition的等待隊列中來回移動實現的,每個隊列的意義不同,Condition作為一個條件類,很好的自己維護了一個等待信號的隊列,并在適時的時候將結點加入到AQS的等待隊列中來實現的喚醒操作

以上就是解析java中的condition的詳細內容,更多關于java condition的資料請關注好吧啦網其它相關文章!

標簽: Java
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
国产女优一区| 日韩av一区二区在线影视| 久久97久久97精品免视看秋霞| 久久99伊人| 亚洲精品亚洲人成在线观看| 男人的天堂久久精品| 亚洲欧洲另类| 视频在线在亚洲| 91精品电影| 伊人久久婷婷| 在线视频免费在线观看一区二区| 亚洲三级欧美| 欧美日韩色图| 首页亚洲欧美制服丝腿| 蜜桃久久av一区| 国产精品久一| 精品国产亚洲一区二区三区大结局| 人人精品人人爱| 日韩精品欧美成人高清一区二区| 日本一不卡视频| 日韩福利视频网| 狠狠久久伊人| 精品久久视频| 色爱综合网欧美| 久久久一本精品| 日韩视频在线一区二区三区 | 亚洲天堂1区| 成人羞羞视频播放网站| 亚洲综合三区| 免费一级欧美片在线观看网站| 日韩深夜视频| 中文字幕亚洲在线观看| 国产精品视频一区二区三区| 日韩不卡一二三区| 国产精品二区影院| 国产一区2区| 日韩深夜视频| 午夜影院一区| 亚洲精品亚洲人成在线观看| 免费久久精品| 69堂免费精品视频在线播放| 久久国产精品免费精品3p| sm捆绑调教国产免费网站在线观看| 国产精品久久久久久久久久久久久久久 | 99久久精品网| 亚洲作爱视频| 国产精品视频一区二区三区四蜜臂 | 精品国产黄a∨片高清在线| 精品国产aⅴ| 国产资源在线观看入口av| 亚洲国产成人二区| 日韩国产欧美三级| 亚洲播播91| 亚洲精品无播放器在线播放| 岛国av在线播放| 亚洲制服欧美另类| 麻豆精品网站| 夜久久久久久| 99久久www免费| 久久久久久久久久久妇女| 日本不卡在线视频| 午夜在线精品偷拍| 国产成人久久| 久久久免费人体| 久久国产日韩| 国产精品久久久久久久久久齐齐 | 日韩中文视频| 麻豆国产欧美日韩综合精品二区| 99国产精品私拍| 99精品美女| 亚洲福利国产| 国产一区二区三区四区五区传媒| 国产精品视频一区二区三区四蜜臂| 久久国产免费看| 国产一区调教| 91精品蜜臀一区二区三区在线| 香蕉成人av| 免费人成网站在线观看欧美高清| 蜜臀av亚洲一区中文字幕| 亚洲日韩中文字幕一区| 国产免费久久| 亚洲成人一区在线观看| 99国产精品私拍| 91亚洲无吗| 国际精品欧美精品| av一区二区高清| 亚洲激精日韩激精欧美精品| 日日夜夜免费精品视频| 免费亚洲婷婷| 欧美专区18| jizzjizz中国精品麻豆| 亚洲一区欧美二区| 你懂的国产精品| 中文欧美日韩| 久久精品国产99国产精品| 99精品美女| 国产经典一区| 亚洲在线网站| 四虎8848精品成人免费网站| 视频一区二区三区中文字幕| 国产精成人品2018| 1024精品一区二区三区| 少妇精品久久久一区二区| 久久伊人久久| 日韩欧美中文字幕一区二区三区| 欧美不卡高清一区二区三区| 午夜电影一区| 欧美日韩少妇| 国产色播av在线| 国产精品白丝一区二区三区| 丝袜国产日韩另类美女| 日本午夜大片a在线观看| 欧美日韩中出| 亚洲一区二区日韩| 午夜欧美理论片| 久久久久国产精品一区三寸| 亚洲日本欧美| 亚洲视频播放| 国内激情久久| 欧美日韩一区二区三区视频播放| 久久99性xxx老妇胖精品| 日韩精品乱码av一区二区| 国产视频一区欧美| 黄色日韩在线| 亚洲精品888| 最新亚洲激情| 黄色国产精品| 香蕉成人久久| 亚洲欧美久久| 日韩中文字幕亚洲一区二区va在线| 韩日一区二区三区| 成人在线视频免费| 国产成人1区| 三级在线看中文字幕完整版| 精品国产免费人成网站| 成人午夜在线| 久久久精品网| 国产精品三上| 日韩一区二区三区精品视频第3页| 免费成人av在线播放| 午夜欧美精品久久久久久久| 美日韩精品视频| **爰片久久毛片| 精品一区二区三区中文字幕在线| 精品一区二区三区在线观看视频| 欧美国产美女| 91精品国产自产在线观看永久∴| 日韩精品一区二区三区免费观影 | 91亚洲国产成人久久精品| 欧美成a人免费观看久久| 欧美成人精品| 亚洲精品国模| 国产精品色在线网站| 麻豆成人在线| 欧美黄色一区二区| 精品日本视频| 国产婷婷精品| 麻豆一区二区在线| 私拍精品福利视频在线一区| 最新国产精品| 日韩欧美一区二区三区免费看| 亚洲一区二区三区久久久| 九九九精品视频| 在线观看亚洲精品福利片| 老司机免费视频一区二区三区| 999国产精品| 久久精品xxxxx| 久久亚洲成人| 久久不卡国产精品一区二区| 婷婷综合亚洲| 国产精品一区二区99| 日本久久成人网| 免费在线播放第一区高清av| 久久亚洲影院| 91免费精品国偷自产在线在线| 久久久9色精品国产一区二区三区| 色偷偷色偷偷色偷偷在线视频| 欧美日韩第一| 国产精品一区二区免费福利视频| 在线日韩中文| 成人高清一区| 国产精品亚洲综合久久| 噜噜噜久久亚洲精品国产品小说| 精品免费视频| 久久精品 人人爱| 激情偷拍久久| 日韩精品首页| 午夜av不卡| 福利一区二区三区视频在线观看| 日本午夜精品视频在线观看| 夜夜精品视频| 99日韩精品| 香蕉久久99| 久久精品一区二区三区中文字幕| 日本一区中文字幕| 天堂久久av| 国产亚洲福利| 欧美中文一区二区| 99精品网站| 欧美日韩高清|