相同点
1、LinkedBlockingQueue和ArrayBlockingQueue都实现了BlockingQueue接口,继承了AbstractQueue抽象类。
LinkedBlockingQueue:
ArrayBlockingQueue:
2、LinkedBlockingQueue和ArrayBlockingQueue都是可阻塞的队列,内部都是使用ReentrantLock和Condition来保证生产和消费的同步;当队列为空,消费者线程被阻塞;当队列装满,生产者线程被阻塞。
LinkedBlockingQueue:
ArrayBlockingQueue:
3、都是使用Condition的方法来同步和通信:await()和signal()。
不同点
1、锁机制不同:
LinkedBlockingQueue中的锁是分离的,生产者的锁为PutLock,消费者的锁为takeLock。而ArrayBlockingQueue生产者和消费者使用的是同一把锁;
LinkedBlockingQueue:
ArrayBlockingQueue:
2、他们的底层实现机制也不同
LinkedBlockingQueue内部维护的是一个链表结构,在生产和消费的时候,需要创建Node对象进行插入或移除,大批量数据的系统中,其对于GC的压力会比较大。而ArrayBlockingQueue内部维护了一个数组,在生产和消费的时候,是直接将枚举对象插入或移除的,不会产生或销毁任何额外的对象实例。
LinkedBlockingQueue:
ArrayBlockingQueue的底层:
3、构造方法不同:
LinkedBlockingQueue有默认的容量大小为:Integer.MAX_VALUE,当然也可以传入指定的容量大小。ArrayBlockingQueue在初始化的时候,必须传入一个容量大小的值。
LinkedBlockingQueue:
ArrayBlockingQueue:
4、clear()机制不同。
LinkedBlockingQueue的clear()方法中,会加两把锁。ArrayBlockingQueue的clear()方法中只加一把锁。
LinkedBlockingQueue:
public void clear() {
fullyLock();
try {
for (Node<E> p, h = head; (p = h.next) != null; h = p) {
h.next = h;
p.item = null;
}
head = last;
// assert head.item == null && head.next == null;
if (count.getAndSet(0) == capacity)
notFull.signal();
} finally {
fullyUnlock();
}
}
ArrayBlockingQueue执行clear()的机制:
public void clear() {
final Object[] items = this.items;
final ReentrantLock lock = this.lock;
lock.lock();
try {
int k = count;
if (k > 0) {
final int putIndex = this.putIndex;
int i = takeIndex;
do {
items[i] = null;
if (++i == items.length)
i = 0;
} while (i != putIndex);
takeIndex = putIndex;
count = 0;
if (itrs != null)
itrs.queueIsEmpty();
for (; k > 0 && lock.hasWaiters(notFull); k--)
notFull.signal();
}
} finally {
lock.unlock();
}
}
5、统计元素的个数
LinkedBlockingQueue中使用了一个AtomicInteger对象来统计元素的个数,ArrayBlockingQueue则使用int类型来统计元素。
LinkedBlockingQueue中统计元素个数的源码:
ArrayBlockingQueue中统计元素个数的源码: