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;
}