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