【JAVA並發編程實戰】11、有界緩衝的實現,java實戰
1、有界緩衝的基類
package cn.xf.cp.ch14;/** * *功能:有界緩衝實現基類 *時間:下午2:20:00 *檔案:BaseBoundedBuffer.java *@author Administrator * * @param <V> */public class BaseBoundedBuffer<V>{ private final V[] buf; private int tail; private int head; private int count; public BaseBoundedBuffer(int capacity) { //初始化數組 this.buf = (V[]) new Object[capacity]; } //放入一個資料,final方法無法被重寫 protected synchronized final void doPut(V v) { buf[tail] = v; if(++tail == buf.length) { tail = 0; } //插入一個方法,總量++ ++count; } /** * 取出一個資料 * @return */ protected synchronized final V doTake() { V v = buf[head]; buf[head] = null; if(++head == buf.length) { head = 0; } --count; return v; } //通過對count的判斷,來確定數組是否是滿的 public synchronized final boolean isFull() { return count == buf.length; } public synchronized final boolean isEmpty() { return count == 0; }}
2、判定前提條件再執行操作
package cn.xf.cp.ch14;/** * *功能:對插入和擷取元素操作進行先行檢查,然後執行操作,校正不通過不予操作 *時間:下午2:33:41 *檔案:GrumpyBoundedBuffer.java *@author Administrator * * @param <V> */public class GrumpyBoundedBuffer<V> extends BaseBoundedBuffer<V>{ public GrumpyBoundedBuffer(int size) { super(size); } public synchronized void put(V v) throws Exception { //如果是滿的隊列,就無法插入新的元素 if(this.isFull()) { throw new Exception("隊列超出"); } this.doPut(v); } //同理,隊列為空白的就無法取出新的元素 public synchronized V take() throws Exception { if(this.isEmpty()) { throw new Exception("隊列中無元素"); } return this.doTake(); }}
3、通過輪詢與休眠來實現簡單的阻塞
package cn.xf.cp.ch14;/** * *功能:通過輪詢與休眠來實現簡單的阻塞 *時間:下午2:55:54 *檔案:SleepyBoundedBuffer.java *@author Administrator * * @param <V> */public class SleepyBoundedBuffer<V> extends BaseBoundedBuffer<V>{ //2s private static final long SLEEP_GRANULARITY = 2000; public SleepyBoundedBuffer(int capacity) { super(capacity); } //放入隊列的時候 public void put(V v) throws InterruptedException { while(true) { //這裡不對迴圈上鎖,不然這個鎖就無法釋放了,不對休眠上鎖,休眠上鎖,在休眠的時候別人也無法操作,永遠都不可能有元素出去 synchronized (this) { //如果隊列不是滿的,那麼就放入元素 if(!this.isFull()) { this.doPut(v); return; } } //否則休眠,退出cpu佔用 Thread.sleep(SLEEP_GRANULARITY); } } public V take() throws InterruptedException { while(true) { //這裡不對迴圈上鎖,不然這個鎖就無法釋放了,不對休眠上鎖,休眠上鎖,在休眠的時候別人也無法操作,永遠都不可能有新的元素進來 synchronized(this) { //如果數組部位空,那麼就可以取出資料 if(!this.isEmpty()) { return this.doTake(); } //如果隊列為空白,休眠幾秒再試 } Thread.sleep(SLEEP_GRANULARITY); } } }
4、條件隊列
package cn.xf.cp.ch14;/** * *功能:使用條件隊列 *時間:下午3:32:04 *檔案:BoundedBuffer.java *@author Administrator * * @param <V> */public class BoundedBuffer<V> extends BaseBoundedBuffer<V>{ public BoundedBuffer(int capacity) { super(capacity); } /** * 放入資料元素 * @param v * @throws InterruptedException */ public synchronized void put(V v) throws InterruptedException { while(this.isFull()) { //這裡掛起程式,會釋放鎖 this.wait(); } //如果隊列不為滿的,那麼程式被喚醒之後從新擷取鎖 this.doPut(v); //執行結束,喚醒其他隊列 this.notifyAll(); } public synchronized V take() throws InterruptedException { while(this.isEmpty()) { this.wait(); } V v = this.doTake(); this.notifyAll(); return v; } }