java.util.concurrent包提供的容器(Queue、List、Set)、Map从命名上可以大概分为Concurrent* 、CopyOnWrite和Blocking等三类:
绝大部分Queue都是实现了BlockingQueue接口。Blocking意味着提供了特定的等待性操作,take时等待元素进队,put是等待队列出现空位。
LinkedBlockingQueue的实现:
/** Lock held by take, poll, etc */ private final ReentrantLock takeLock = new ReentrantLock(); /** Wait queue for waiting takes */ private final Condition notEmpty = takeLock.newCondition(); /** Lock held by put, offer, etc */ private final ReentrantLock putLock = new ReentrantLock(); /** Wait queue for waiting puts */ private final Condition notFull = putLock.newCondition();
与ArrayBlockingQueue不同,后者的notEmpty、notFull都是同一个再入锁的条件变量。而LinkedBlockingQueue改进了锁操作的粒度,头、尾操作使用不同的锁。
LinkedBlockingQueue的take操作:
public E take() throws InterruptedException { final E x; final int c; final AtomicInteger count = this.count; final ReentrantLock takeLock = this.takeLock; takeLock.lockInterruptibly(); try { while (count.get() == 0) { notEmpty.await(); } x = dequeue(); c = count.getAndDecrement(); if (c > 1) notEmpty.signal(); } finally { takeLock.unlock(); } if (c == capacity) signalNotFull(); return x; }