1. 程式人生 > >JAVA多執行緒之——執行緒通訊 Condition

JAVA多執行緒之——執行緒通訊 Condition

執行緒的通訊
前面學習了用wait/notify的方式進行執行緒通訊。今天學習一種更加強大的執行緒通訊方式Condition.Condition的強大之處就是可以為執行緒建立不同的Condition。然後可以喚醒任意指定阻塞的執行緒。Condition之所以能為一個執行緒建立不同的Condition,是因為它也維護著一個阻塞的條件佇列。它跟AQS等待佇列通過執行緒的等待、喚醒建立關係。
1.每當AQS佇列中的執行緒呼叫Condition.await()方法,AQS就會把當前執行緒從佇列中移除,並加入到Condition佇列的尾部並阻塞,然後等待喚醒。
2.每當AQS佇列中執行緒對Condition佇列中的某個阻塞執行緒進行了Condition.sinal()方法,Condition佇列就會把該執行緒從佇列中移除,執行緒加入AQS等待佇列末尾,等待獲取鎖。
通過Condition實現多執行緒的消費者、生產者模式來進一步理解:


public class ConditionTest {


    static class Depot{

        private int size;
        private ReentrantLock  lock = null;
        private  Condition  notEmptyCondition = null ;
        private  Condition  notFullCondition = null;
        private  List<Integer> depots;


        public
Depot(int size) { this.size = size; lock = new ReentrantLock(); notEmptyCondition = lock.newCondition(); notFullCondition = lock.newCondition(); depots = new LinkedList<Integer>(); } /** * 每次生產count個產品 * @param count */
public void producer(int count) { lock.lock(); try { while(depots.size() > 0){ System.out.println("倉庫已經有鏟產品了,可以開始消費了"); notFullCondition.await(); //倉庫滿了進行等待消費 } int actCount = (count + depots.size()) > size ? (size - depots.size()) : count; //如果生產的數量和現有的數量大於總數,就只生產倉庫剩餘的最大容量數 System.out.println(Thread.currentThread().getName() + "執行緒開始生產"); for(int i = 0; i < actCount; i++ ) { depots.add(i); } System.out.println(Thread.currentThread().getName() + "生產完畢,當前倉庫有" + depots.size() + "個產品"); notEmptyCondition.signal(); } catch (InterruptedException e) { e.printStackTrace(); }finally { lock.unlock(); } } public void consumer(int count) { lock.lock(); try { while(depots.size() == 0) { System.out.println("當前倉庫為空,等待生產"); notEmptyCondition.await(); } int actCount = (depots.size() > count ) ? count : depots.size();//如果當前倉庫剩餘容量大於消費容量,就消費消費個,如果消費的容量比倉庫剩餘容量大,就把剩餘的都消費掉。 System.out.println(Thread.currentThread().getName() + "執行緒開始消費"); Iterator<Integer> iterator = depots.iterator(); while(iterator.hasNext() && actCount > 0 ) { iterator.next(); iterator.remove(); actCount--; } System.out.println(Thread.currentThread().getName() + "消費完畢,當前倉庫有" + depots.size() + "個產品"); notFullCondition.signal(); } catch (Exception e) { e.printStackTrace(); }finally { lock.unlock(); } } } public static void main(String[] args) { final Depot depot = new Depot(100); for(int i = 0; i < 30; i++) { Thread thread = new Thread(new Runnable() { @Override public void run() { while(true){ depot.producer(40); } } },"producer-" + i ); thread.start(); } for(int i = 0; i < 30; i++) { Thread thread1 = new Thread(new Runnable() { @Override public void run() { while(true){ depot.consumer(80); } } },"consumer-" + i); thread1.start(); } } }

某一次執行部分結果

producer-20執行緒開始生產
producer-20生產完畢,當前倉庫有40個產品
倉庫已經有鏟產品了,可以開始消費了
cusume-2執行緒開始消費
cusume-2消費完畢,當前倉庫有0個產品
當前倉庫為空,等待生產
producer-21執行緒開始生產
producer-21生產完畢,當前倉庫有40個產品
倉庫已經有鏟產品了,可以開始消費了
cusume-28執行緒開始消費
cusume-28消費完畢,當前倉庫有0個產品
當前倉庫為空,等待生產
producer-15執行緒開始生產
producer-15生產完畢,當前倉庫有40個產品
倉庫已經有鏟產品了,可以開始消費了
cusume-11執行緒開始消費
cusume-11消費完畢,當前倉庫有0個產品
當前倉庫為空,等待生產
producer-24執行緒開始生產
producer-24生產完畢,當前倉庫有40個產品
倉庫已經有鏟產品了,可以開始消費了
cusume-14執行緒開始消費
cusume-14消費完畢,當前倉庫有0個產品
當前倉庫為空,等待生產
producer-19執行緒開始生產
producer-19生產完畢,當前倉庫有40個產品
倉庫已經有鏟產品了,可以開始消費了
cusume-4執行緒開始消費
cusume-4消費完畢,當前倉庫有0個產品
當前倉庫為空,等待生產
producer-25執行緒開始生產
producer-25生產完畢,當前倉庫有40個產品
倉庫已經有鏟產品了,可以開始消費了
cusume-15執行緒開始消費
cusume-15消費完畢,當前倉庫有0個產品
當前倉庫為空,等待生產
producer-8執行緒開始生產
producer-8生產完畢,當前倉庫有40個產品
倉庫已經有鏟產品了,可以開始消費了
cusume-20執行緒開始消費
cusume-20消費完畢,當前倉庫有0個產品
當前倉庫為空,等待生產
producer-29執行緒開始生產
producer-29生產完畢,當前倉庫有40個產品
倉庫已經有鏟產品了,可以開始消費了
cusume-5執行緒開始消費
cusume-5消費完畢,當前倉庫有0個產品
當前倉庫為空,等待生產
producer-1執行緒開始生產
producer-1生產完畢,當前倉庫有40個產品
倉庫已經有鏟產品了,可以開始消費了
cusume-0執行緒開始消費
cusume-0消費完畢,當前倉庫有0個產品
當前倉庫為空,等待生產
producer-26執行緒開始生產
producer-26生產完畢,當前倉庫有40個產品
倉庫已經有鏟產品了,可以開始消費了
cusume-18執行緒開始消費
cusume-18消費完畢,當前倉庫有0個產品
當前倉庫為空,等待生產
producer-16執行緒開始生產
producer-16生產完畢,當前倉庫有40個產品
倉庫已經有鏟產品了,可以開始消費了
cusume-19執行緒開始消費
cusume-19消費完畢,當前倉庫有0個產品
當前倉庫為空,等待生產
producer-3執行緒開始生產
producer-3生產完畢,當前倉庫有40個產品
倉庫已經有鏟產品了,可以開始消費了
cusume-12執行緒開始消費
cusume-12消費完畢,當前倉庫有0個產品
當前倉庫為空,等待生產
producer-7執行緒開始生產
producer-7生產完畢,當前倉庫有40個產品
倉庫已經有鏟產品了,可以開始消費了
cusume-22執行緒開始消費
cusume-22消費完畢,當前倉庫有0個產品
當前倉庫為空,等待生產
producer-11執行緒開始生產
producer-11生產完畢,當前倉庫有40個產品
倉庫已經有鏟產品了,可以開始消費了
cusume-26執行緒開始消費
cusume-26消費完畢,當前倉庫有0個產品
當前倉庫為空,等待生產
producer-2執行緒開始生產
producer-2生產完畢,當前倉庫有40個產品
倉庫已經有鏟產品了,可以開始消費了
cusume-1執行緒開始消費
cusume-1消費完畢,當前倉庫有0個產品
當前倉庫為空,等待生產
producer-28執行緒開始生產
producer-28生產完畢,當前倉庫有40個產品
倉庫已經有鏟產品了,可以開始消費了
cusume-23執行緒開始消費
cusume-23消費完畢,當前倉庫有0個產品
當前倉庫為空,等待生產
producer-10執行緒開始生產
producer-10生產完畢,當前倉庫有40個產品
倉庫已經有鏟產品了,可以開始消費了
cusume-27執行緒開始消費
cusume-27消費完畢,當前倉庫有0個產品
當前倉庫為空,等待生產

上面是簡單模擬生產者消費者的例子。當然其中還有很多變化。還有就是用List來做儲存。這個在多執行緒高併發環境下是不安全的等等。以後會學習JUC下的集合以及一些併發類。就能寫出越來越安全的生產者消費真模式。

相關推薦

java執行-執行間的通訊

一個生產者與一個消費者 使用的方法: wait():使執行緒停止並釋放鎖。 notify():叫醒執行緒。 例子 工具類 public class ValueObject { public static String value=""; }

【本人禿頂程式設計師】JAVA執行執行間的通訊方式

←←←←←←←←←←←← 我都禿頂了,還不點關注! 一,介紹 本總結我對於JAVA多執行緒中執行緒之間的通訊方式的理解,主要以程式碼結合文字的方式來討論執行緒間的通訊,故摘抄了書中的一些示例程式碼。 二,執行緒間的通訊方式 ①同步 這裡講的同步是指多個執行緒通過synchro

JAVA執行——執行通訊 Condition

執行緒的通訊 前面學習了用wait/notify的方式進行執行緒通訊。今天學習一種更加強大的執行緒通訊方式Condition.Condition的強大之處就是可以為執行緒建立不同的Condition。然後可以喚醒任意指定阻塞的執行緒。Condition之所以能

Java執行執行之間的通訊方式

一,介紹本總結我對於JAVA多執行緒中執行緒之間的通訊方式的理解,主要以程式碼結合文字的方式來討論執行緒間的通訊,故摘抄了書中的一些示例程式碼。二,執行緒間的通訊方式①同步這裡講的同步是指多個執行緒通過synchronized關鍵字這種方式來實現執行緒間的通訊。參考示例:pu

java執行執行通訊

在多執行緒機制中,執行緒之間需要傳輸資訊。一般有以下幾種通訊機制: 共享物件:通過在共享物件中設定訊號量,多個執行緒通過讀取、修改該訊號量來通訊。 wait/notify()方法:執行緒之間通過呼叫wait()、notify()方法實現執行緒等待、喚醒狀態,

Java執行執行通訊--等待(wait)/通知(notify)機制,等待/通知交叉備份例項

1、什麼是等待/通知機制   等待/通知機制在生活中比比皆是,比如在就餐時就會出現,如圖所示。      廚師和服務員之間的互動要在“菜品傳遞臺”上,在這期間會有幾個問題:   1).廚師做完一道菜的時間不確定,所以廚師將菜品放到‘菜品傳遞言,上的時間也

java執行 執行協作

也是網上看的一道題目:關於假如有Thread1、Thread2、Thread3、Thread4四條執行緒分別統計C、D、E、F四個盤的大小,所有執行緒都統計完畢交給Thread5執行緒去做彙總,應當如何實現? 蒐集整理了網上朋友提供的方法,主要有: 1. 多執行緒都是Thread或

Java基礎執行執行安全-同步鎖三種形式

首先,我們通過一個案例,演示執行緒的安全問題: 電影院要賣票,我們模擬電影院的賣票過程。假設要播放的電影是 “葫蘆娃大戰奧特曼”,本次電影的座位共100個(本場電影只能賣100張票)。我們來模擬電影院的售票視窗,實現多個視窗同時賣 “終結者”這場電影票(多個視窗一起賣這100張票)需要視窗

Java基礎學習——執行執行

1.執行緒池介紹     執行緒池是一種執行緒使用模式。執行緒由於具有空閒(eg:等待返回值)和繁忙這種不同狀態,當數量過多時其建立、銷燬、排程等都會帶來開銷。執行緒池維護了多個執行緒,當分配可併發執行的任務時,它負責排程執行緒執行工作,執行完畢後執行緒不關閉而是返回執行緒池,

Java執行執行排程(二)

(一)執行緒優先順序 執行緒優先順序用1~10表示,10表示優先順序最高,預設值是5.每個優先順序對應一個Thread類的公用靜態常量。如 public static final int MIN_PRIORITY = 1; public static final int NO

Java中的執行執行間的通訊

                                         兩個

Java筆記-執行執行控制

執行緒控制 我們已經知道了執行緒的排程,接下來我們就可以使用如下方法物件執行緒進行控制。 1.執行緒休眠 public static void sleep(long millis):讓當前執行緒處於暫停狀態,millis引數毫秒值,即暫停時間。 程式

Java筆記-執行執行死鎖問題加簡單舉例

死鎖 導致死鎖的原因 Java中死鎖最簡單的情況是,一個執行緒T1持有鎖L1並且申請獲得鎖L2,而另一個執行緒T2持有鎖L2並且申請獲得鎖L1,因為預設的鎖申請操作都是阻塞的,所以執行緒T1和T2永遠被阻塞了。導致了死鎖。 這是最容易理解也是最簡單的死

[JDK] Java 執行 執行安全

Java 多執行緒 之 執行緒安全 多執行緒併發操作時資料共享如何安全進行? 執行緒安全與共享 多執行緒操作靜態變數(非執行緒安全) SynchronizedLockTest: /** * <p> * 測試類 * </p>

讀書筆記:java執行執行同步

閱讀的書籍:《java瘋狂講義》 關鍵詞:執行緒安全問題,同步程式碼塊,同步方法,釋放同步監視器的鎖定,同步鎖,死鎖 執行緒安全問題:當使用多個執行緒來訪問同一個資料時,會導致一些錯誤情況的發生 到底什麼是執行緒安全問題呢,先看一個經典的案例:銀行取錢的問題

Java執行執行的狀態以及之間的切換(轉)

 博主最近幾天在面試的時候,被面試官問到了Java多執行緒的幾種狀態,無疑博主已經把該忘記的都忘記了,很是尷尬,回到家中在網上找到一篇部落格,博主認真閱讀了此文章,寫的很詳細,現轉載分享給大家: Java中執行緒的狀態分為6種。     1. 初始(N

Java執行執行排程詳解

排程的概念 給定時間結點,時間間隔,任務次數,然後自動執行任務 應用場景舉例 1.日誌清理:每隔三個月,清理公司日誌檔案 2.日誌備份:每個一週,備份公司檔案 3.工資結算:每個月29號,考勤彙報,業務結算,計算工資 排程的實現方式:

Java執行執行模式Immutable模式

Immutable模式 概念:保障資料的安全性,不可變的一種模式。 舉例:java.lang.string 實現了Immutable模式。無需為類中的方法宣告為synchronized,無論被多少個執行緒訪問String物件,物件不可變,不需要考慮執行緒的互斥處

Java執行執行返回值

                對於Java多執行緒的理解,我以前僅僅侷限於實現Runnable介面或者繼承Thread類,然後重寫run()方法,最後start()呼叫就算完事,但是一旦涉及死鎖以及對共享資源的訪問和隨時監控執行緒的狀態和執行順序等等就不行了,所以現在開始看Thinking in java的

_158_java_執行執行間的通訊方式

轉自https://www.cnblogs.com/hapjin/p/5492619.html,感謝作者的無私分享。  一,介紹 本總結我對於JAVA多執行緒中執行緒之間的通訊方式的理解,主要以程式碼結合文字的方式來討論執行緒間的通訊,故摘抄了書中的一些示例程式碼。