1. 程式人生 > >Java多執行緒之Condition

Java多執行緒之Condition

Condition,Condition 將 Object 監視器方法(wait、notify 和 notifyAll)分解成截然不同的物件,以便通過將這些物件與任意 Lock 實現組合使用,為每個物件提供多個等待 set (wait-set)。其中,Lock 替代了 synchronized 方法和語句的使用,Condition 替代了 Object 監視器方法的使用。下面將之前寫過的一個執行緒通訊的例子替換成用Condition實現(Java執行緒(三)),程式碼如下:
public class ThreadTest2 {  
    public static void main(String[] args) {  
        final Business business = new
Business(); new Thread(new Runnable() { @Override public void run() { threadExecute(business, "sub"); } }).start(); threadExecute(business, "main"); } public static void threadExecute(Business business, String threadType) { for
(int i = 0; i < 100; i++) { try { if("main".equals(threadType)) { business.main(i); } else { business.sub(i); } } catch (InterruptedException e) { e.printStackTrace(); } } } } class Business { private
boolean bool = true; private Lock lock = new ReentrantLock(); private Condition condition = lock.newCondition(); public /*synchronized*/ void main(int loop) throws InterruptedException { lock.lock(); try { while(bool) { condition.await();//this.wait(); } for(int i = 0; i < 100; i++) { System.out.println("main thread seq of " + i + ", loop of " + loop); } bool = true; condition.signal();//this.notify(); } finally { lock.unlock(); } } public /*synchronized*/ void sub(int loop) throws InterruptedException { lock.lock(); try { while(!bool) { condition.await();//this.wait(); } for(int i = 0; i < 10; i++) { System.out.println("sub thread seq of " + i + ", loop of " + loop); } bool = false; condition.signal();//this.notify(); } finally { lock.unlock(); } } }
    在Condition中,用await()替換wait(),用signal()替換notify(),用signalAll()替換notifyAll(),傳統執行緒的通訊方式,Condition都可以實現,這裡注意,Condition是被繫結到Lock上的,要建立一個Lock的Condition必須用newCondition()方法。
    這樣看來,Condition和傳統的執行緒通訊沒什麼區別,Condition的強大之處在於它可以為多個執行緒間建立不同的Condition,下面引入API中的一段程式碼,加以說明。
class BoundedBuffer {  
   final Lock lock = new ReentrantLock();//鎖物件  
   final Condition notFull  = lock.newCondition();//寫執行緒條件   
   final Condition notEmpty = lock.newCondition();//讀執行緒條件   

   final Object[] items = new Object[100];//快取佇列  
   int putptr/*寫索引*/, takeptr/*讀索引*/, count/*佇列中存在的資料個數*/;  

   public void put(Object x) throws InterruptedException {  
     lock.lock();  
     try {  
       while (count == items.length)//如果佇列滿了   
         notFull.await();//阻塞寫執行緒  
       items[putptr] = x;//賦值   
       if (++putptr == items.length) putptr = 0;//如果寫索引寫到佇列的最後一個位置了,那麼置為0  
       ++count;//個數++  
       notEmpty.signal();//喚醒讀執行緒  
     } finally {  
       lock.unlock();  
     }  
   }  

   public Object take() throws InterruptedException {  
     lock.lock();  
     try {  
       while (count == 0)//如果佇列為空  
         notEmpty.await();//阻塞讀執行緒  
       Object x = items[takeptr];//取值   
       if (++takeptr == items.length) takeptr = 0;//如果讀索引讀到佇列的最後一個位置了,那麼置為0  
       --count;//個數--  
       notFull.signal();//喚醒寫執行緒  
       return x;  
     } finally {  
       lock.unlock();  
     }  
   }   
 }  
    這是一個處於多執行緒工作環境下的快取區,快取區提供了兩個方法,put和take,put是存資料,take是取資料,內部有個快取佇列,具體變數和方法說明見程式碼,這個快取區類實現的功能:有多個執行緒往裡面存資料和從裡面取資料,其快取佇列(先進先出後進後出)能快取的最大數值是100,多個執行緒間是互斥的,當快取佇列中儲存的值達到100時,將寫執行緒阻塞,並喚醒讀執行緒,當快取佇列中儲存的值為0時,將讀執行緒阻塞,並喚醒寫執行緒,這也是ArrayBlockingQueue的內部實現。下面分析一下程式碼的執行過程:

    1. 一個寫執行緒執行,呼叫put方法;

    2. 判斷count是否為100,顯然沒有100;

    3. 繼續執行,存入值;

    4. 判斷當前寫入的索引位置++後,是否和100相等,相等將寫入索引值變為0,並將count+1;

    5. 僅喚醒讀執行緒阻塞佇列中的一個;

    6. 一個讀執行緒執行,呼叫take方法;

    7. ……

    8. 僅喚醒寫執行緒阻塞佇列中的一個。

    這就是多個Condition的強大之處,假設快取佇列中已經存滿,那麼阻塞的肯定是寫執行緒,喚醒的肯定是讀執行緒,相反,阻塞的肯定是讀執行緒,喚醒的肯定是寫執行緒,那麼假設只有一個Condition會有什麼效果呢,快取佇列中已經存滿,這個Lock不知道喚醒的是讀執行緒還是寫執行緒了,如果喚醒的是讀執行緒,皆大歡喜,如果喚醒的是寫執行緒,那麼執行緒剛被喚醒,又被阻塞了,這時又去喚醒,這樣就浪費了很多時間。

    本文來自:高爽|Coder,原文地址:http://blog.csdn.net/ghsau/article/details/7481142,轉載請註明。

相關推薦

Java執行Condition實現原理和原始碼分析(四)

章節概覽、 1、概述 上面的幾個章節我們基於lock(),unlock()方法為入口,深入分析了獨佔鎖的獲取和釋放。這個章節我們在此基礎上,進一步分析AQS是如何實現await,signal功能。其功能上和synchronize的wait,notify一樣。

Java執行Condition

Condition,Condition 將 Object 監視器方法(wait、notify 和 notifyAll)分解成截然不同的物件,以便通過將這些物件與任意 Lock 實現組合使用,為每個物件提供多個等待 set (wait-set)。其中,Lock 替

java執行ReentrantLock和 Condition

ReentrantLock 是JDK中內建鎖,也稱可重入鎖,API也較為簡單。  Condition 可實現 執行緒間通訊,由ReentrantLock 例項產生即 lock.new Condition(); 下面這個demo模擬最簡單的生產者 消費者模式,Add執行緒模

Java執行JUC包:Condition原始碼學習筆記

若有不正之處請多多諒解,並歡迎批評指正。 請尊重作者勞動成果,轉載請標明原文連結: Condition在JUC框架下提供了傳統Java監視器風格的wait、notify和notifyAll相似的功能。 Condition必須被繫結到一個獨佔鎖上使用。ReentrantLock中獲取Conditi

JAVA執行——執行通訊 Condition

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

Java執行執行併發庫條件阻塞Condition的應用

鎖(Lock/synchronized)只能實現互斥不能實現通訊,Condition的功能類似於在傳統的執行緒技術中的,Object.wait()和Object.notify()的功能,在等待Condition時,允許發生"虛假喚醒",這通常作為對基礎平臺語義的讓步,對於大多

Java執行join()方法

概要 本章,會對Thread中join()方法進行介紹。涉及到的內容包括: 1. join()介紹 2. join()原始碼分析(基於JDK1.7.0_40) 3. join()示例 來源:http://www.cnblogs.com/skywang12345/p/34792

白話理解java執行join()方法

join字面意思是加入,我理解為插隊. 舉例:媽媽在炒菜,發現沒喲醬油了,讓兒子去打醬油,兒子打完醬油,媽媽炒完菜,全家一起吃 package cn.yh.thread01; /** * * 打醬油的例子 */ public class Demo03 { public stat

細說Java 執行記憶體可見性

前言: 討論學習Java中的記憶體可見性、Java記憶體模型、指令重排序、as-if-serial語義等多執行緒中偏向底層的一些知識,以及synchronized和volatile實現記憶體可見性的原理和方法。 1、可見性介紹 可見性:一個執行緒對共用變數值的修改,能夠及時地被其他執行緒

java執行 執行協作

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

java執行鎖機制二

網上看到一個題目,題目是這樣:Java多執行緒,啟動四個執行緒,兩個執行加一,另外兩個執行減一。 針對該問題寫了一個程式,測試通過,如下: class Sync { static int count = 0; public void add() {

java執行鎖機制一

網上看了一篇關於java synchronized關鍵字使用的很好的文章,現將其簡要總結一下,加深理解。 先總結兩個規則: synchronized鎖住的是括號裡的物件,而不是程式碼。對於非static的synchronized方法,鎖的就是物件本身也就是this。 多個執行緒

java執行Phaser

java多執行緒技術提供了Phaser工具類,Phaser表示“階段器”,用來解決控制多個執行緒分階段共同完成任務的情景問題。其作用相比CountDownLatch和CyclicBarrier更加靈活,例如有這樣的一個題目:5個學生一起參加考試,一共有三道題,要求所有學生到齊才能開始考試,全部同學都

Java執行——ThreadLocal

ThreadLocal是什麼:每一個ThreadLocal能夠放一個執行緒級別的變數,也就是說,每一個執行緒有獨自的變數,互不干擾。以此達到執行緒安全的目的,並且一定會安全。 實現原理: 要了解實現原理,我們先看set方法 public void set(T value) { T

java執行Lock--顯式鎖

Lock與Synchronized簡介 Synchornized相信大家用的已經比較熟悉了,這裡我就不介紹它的用法了 Synchronized被稱為同步鎖或者是隱式鎖,隱式鎖與顯式鎖區別在於,隱式鎖的獲取和釋放都需要出現在一個塊結構中,而且是有順序的,獲取鎖的順序和釋放鎖的順序必須相反,就是說,

Java執行Executor框架

在前面的這篇文章中介紹了執行緒池的相關知識,現在我們來看一下跟執行緒池相關的框架--Executor。 一.什麼是Executor 1.Executor框架的兩級排程模型 在HotSpot VM的執行緒模型中,Java執行緒(java.lang.Thread)被一對一對映為本地作業系統執

java執行Executor

程式 程序:執行的程式 執行緒:程序中負責程式執行的執行單元,一個程序至少包括一個執行緒。 單執行緒:一個程序一個執行緒 多執行緒:一個程序多個執行緒   多執行緒是為了更好的利用CPU,提高程式執行的速度。 實現方式:繼承Thread類、實現Runnabl

Java執行學習---Condition和wait、notify(十三)

1.問題:實現兩個執行緒交叉執行(Condition和wait、notify都可以實現) public class ConditionStudy { public static void main(String[] args) { //執行緒程式碼 BussinessTes

java執行(二)鎖

一,鎖 在物件的建立時java會為每個object物件分配一個monitor( 監視器或者監視鎖),當某個物件的同步方法(synchronized methods )被多個執行緒呼叫時,該物件的monitor將負責處理這些訪問的併發獨佔要求。 當一個執行緒呼叫一個物件的同步方法時(sy

Java執行鎖優化策略

轉載 http://www.cnblogs.com/ygj0930/p/6561264.html 編碼過程中可採取的鎖優化的思路有以下幾種: 1:減少鎖持有時間 例如:對一個方法加鎖,不如對方法中需要同步的幾行程式碼加鎖; 2:減小鎖粒度 例如: