Lock && Condition_實現有界緩存java
Lock是一種廣義的內置鎖,Condition也是一種廣義的內置條件隊列。緩存
內置條件隊列存在一些缺陷。每一個內置鎖都只能有一個相關的條件隊列,於是多個線程可能在同一個條件隊列上等待不一樣的條件謂詞,而且在最多見的加鎖模式下公開條件隊列對象。併發
這些因素都使得沒法知足在使用notifyAll時全部等待線程爲同一類型的需求。若是想編寫一個帶有多個條件謂詞的併發對象,或者想得到除了條件隊列可見性的更多控制權,就能夠使用顯示的Lock和Condition而不是內置鎖和內置條件隊列,這是一種更靈活的選擇。ide
Lock比內置鎖提供了更爲豐富的功能,Condition一樣比內置條件隊列提供了更豐富的功能:在每一個鎖上可能存在多個等待、條件等待能夠是可中斷的、基於時限的等待,以及公平的或非公平的隊列操做。this
與內置條件隊列不一樣的是,對於每一個Lock,能夠有任意數量的Condition對象。Condition對象繼承了相關的Lock對象的公平性,對於公平的鎖,線程會依照FIFO順序從Condition.await中釋放。spa
下面這段程序給出了有界緩存的另外一種實現,即使用兩個Condition,分別爲notFull和notEmpty,用於表示」非滿「和」非空「兩個條件謂詞。當緩存爲空時,take將阻塞並等待notEmpty,此時put向notEmpty發送信號,能夠解除任何在take中阻塞的線程。線程
package sync; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * Created with IntelliJ IDEA. * User: ASUS * Date: 14-9-1 * Time: 下午9:20 * To change this template use File | Settings | File Templates. */ public class ConditionBoundedBuffer<T> { protected final Lock lock = new ReentrantLock(); //條件謂詞:notFull private final Condition notFull = lock.newCondition(); //條件謂詞:notEmpty private final Condition notEmpty = lock.newCondition(); private final T[] items; private int tail, head, count; protected ConditionBoundedBuffer(int size) { items = (T[]) new Object[size]; } /** * 阻塞並直到notFull * * @param x * @throws InterruptedException */ public void put(T x) throws InterruptedException { lock.lock(); try { while (count == items.length) { // 阻塞,等待非滿條件 System.out.println("not full await"); notFull.await(); } items[tail] = x; if (++tail == items.length) { tail = 0; } ++count; notEmpty.signal(); } finally { lock.unlock(); } } /** * 阻塞並直到notEmpty * * @return * @throws InterruptedException */ public T take() throws InterruptedException { lock.lock(); try { while (count == 0) { // 阻塞,等待非空條件 System.out.println("not empty await"); notEmpty.await(); //如今有界緩存爲空,要等到非空狀態才能取出元素 } T x = items[head]; items[head] = null; if (++head == items.length) { head = 0; } --count; notFull.signal(); //元素已被取出,通知非滿狀態 return x; } finally { lock.unlock(); } } public static void main(String args[]) { final ConditionBoundedBuffer buffer = new ConditionBoundedBuffer(10); //線程t2打印緩存中的消息 Thread t2 = new Thread(new Runnable() { @Override public void run() { while (true) { try { System.out.println(buffer.take()); } catch (InterruptedException e) { e.printStackTrace(); } } } }); //線程t1放入緩存消息 Thread t1 = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 100; i++) { try { buffer.put(new String("sadsasd")); } catch (InterruptedException e) { e.printStackTrace(); } } } }); t2.start(); t1.start(); } }
============END============code