ArrayBlockingQueue
基本数据结构
final Object[ ] items;
int count;
final ReentrantLock lock;
private final Condition notEmpty;
private final Condition notFull;
插入数据
public void put ( E e) throws InterruptedException {
checkNotNull ( e) ;
final ReentrantLock lock = this . lock;
lock. lockInterruptibly ( ) ;
try {
while ( count == items. length)
notFull. await ( ) ;
enqueue ( e) ;
} finally {
lock. unlock ( ) ;
}
}
private void enqueue ( E x) {
final Object[ ] items = this . items;
items[ putIndex] = x;
if ( ++ putIndex == items. length)
putIndex = 0 ;
count++ ;
notEmpty. signal ( ) ;
}
获取数据
public E take ( ) throws InterruptedException {
final ReentrantLock lock = this . lock;
lock. lockInterruptibly ( ) ;
try {
while ( count == 0 )
notEmpty. await ( ) ;
return dequeue ( ) ;
} finally {
lock. unlock ( ) ;
}
}
private E dequeue ( ) {
final Object[ ] items = this . items;
@SuppressWarnings ( "unchecked" )
E x = ( E ) items[ takeIndex] ;
items[ takeIndex] = null ;
if ( ++ takeIndex == items. length)
takeIndex = 0 ;
count-- ;
if ( itrs != null )
itrs. elementDequeued ( ) ;
notFull. signal ( ) ;
return x;
}
public int remainingCapacity ( ) {
final ReentrantLock lock = this . lock;
lock. lock ( ) ;
try {
return items. length - count;
} finally {
lock. unlock ( ) ;
}
}
put、take通过condition通知机制来完成可阻塞的插入和获取数据
LinkedBlockingQueue
与ArrayBlockingQueue主要区别,LinkedBlockingQueue插入和删除时分别由两个lock(takeLock和putLock)控制线程安全,也由这两个lock生成两个对应的condition(notEmpty和notFull)实现可阻塞的插入和删除数据。采用链表来实现队列。