使用Condition實現生產者消費者
阿新 • • 發佈:2018-12-20
使用Condtion實現生產者消費者可以精確控制喚醒生產者還是消費者執行緒
與synchronized的等待喚醒機制相比Condition具有更多的靈活性以及精確性,這是因為notify()
在喚醒執行緒時是隨機(同一個鎖),而Condition則可通過多個Condition例項物件建立更加精細的執行緒控制,也就帶來了更多靈活性了,我們可以簡單理解為以下兩點
-
通過Condition能夠精細的控制多執行緒的休眠與喚醒。
-
對於一個鎖,我們可以為多個執行緒間建立不同的Condition。
程式碼實現:
1、Condition提供了await()方法將當前執行緒阻塞,並提供signal()方法支援另外一個執行緒將已經阻塞的執行緒喚醒。
2、Condition需要結合Lock使用
3、執行緒呼叫await()方法前必須獲取鎖,呼叫await()方法時,將執行緒構造成節點加入等待佇列,同時釋放鎖,並掛起當前執行緒
4、其他執行緒呼叫signal()方法前也必須獲取鎖,當執行signal()方法時將等待佇列的節點移入到同步佇列,當執行緒退出臨界區釋放鎖的時候(ReentrantLock.unlock),喚醒同步佇列的首個節點
資源:
package com.huige.review; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * @author liuhui * @description * @create 2018/10/18 上午11:22 */ public class ResourceCondtion { private Lock lock = new ReentrantLock(); private Condition consumeCondition = lock.newCondition(); private Condition productCondition = lock.newCondition(); private int number = 0; public void increace(){ lock.lock(); try { while(number > 0){ productCondition.await(); } number ++; System.out.println("生產後"+Thread.currentThread().getName()+" : "+number); consumeCondition.signal(); }catch (Exception e){ e.printStackTrace(); }finally { lock.unlock(); } } public void decreace(){ lock.lock(); try { while(number == 0){ consumeCondition.await(); } number --; System.out.println("消費後"+Thread.currentThread().getName()+" : "+number); productCondition.signal(); }catch (Exception e){ e.printStackTrace(); }finally { lock.unlock(); } } public static void main(String[] args) { ResourceCondtion resource = new ResourceCondtion(); new Thread(new ProductCondition(resource)).start(); new Thread(new ProductCondition(resource)).start(); new Thread(new ConsumeCondition(resource)).start(); new Thread(new ConsumeCondition(resource)).start(); new Thread(new ConsumeCondition(resource)).start(); } }
生產者:
package com.huige.review; /** * @author liuhui * @description * @create 2018/10/18 下午1:51 */ public class ProductCondition implements Runnable { private ResourceCondtion resource ; public ProductCondition(ResourceCondtion resource){ this.resource = resource; } @Override public void run() { for (int i = 0;i<10;i++) { try { Thread.sleep(100); }catch (Exception e){ } resource.increace(); } } }
消費者:
package com.huige.review;
/**
* @author liuhui
* @description
* @create 2018/10/18 下午1:54
*/
public class ConsumeCondition implements Runnable{
private ResourceCondtion resource ;
public ConsumeCondition(ResourceCondtion resource){
this.resource = resource;
}
@Override
public void run() {
for (int i = 0;i<10;i++) {
try {
Thread.sleep(150);
}catch (Exception e){
}
resource.decreace();
}
}
}