天天看点

ArrayBlockingQueue和LinkedBlockingQueue比较

ArrayBlockingQueue和LinkedBlockingQueue异同比较

相同点:

1、LinkedBlockingQueue和ArrayBlockingQueue都实现了BlockingQueue接口;

2、LinkedBlockingQueue和ArrayBlockingQueue都是可阻塞的队列

  内部都是使用ReentrantLock和Condition来保证生产和消费的同步;

  当队列为空,消费者线程被阻塞;当队列装满,生产者线程被阻塞;

3、使用Condition的方法来同步和通信:await()和signal()

不同点:

1、队列中的锁机制不同

       ArrayBlockingQueue中的锁是没有分离的,即生产和消费用的是同一个锁;

       LinkedBlockingQueue中的锁是分离的,即生产用的是putLock,消费是takeLock

2、底层实现机制不一样

       ArrayBlockingQueue中维护数组结构;

       LinkedBlockingQueue中维护链表结构

3、队列大小初始化方式不同

     ArrayBlockingQueue是有界的,必须指定队列的大小;

     LinkedBlockingQueue是无界的,可以不指定队列的大小,但是默认是Integer.MAX_VALUE。当然也可以指定队列大小,从而成为有界的。

4、统计队列中元素个数不一样

       ArrayBlockingQueue中维护一个普通变量int;

       LinkedBlockingQueue中定义一个AtomicInteger对象。

5、在生产或消费时操作不同

     ArrayBlockingQueue基于数组,在生产和消费的时候,是直接将枚举对象插入或移除的,不会产生或销毁任何额外的对象实例;

     LinkedBlockingQueue基于链表,在生产和消费的时候,需要把枚举对象转换为Node<E>进行插入或移除,会生成一个额外的Node对象,这在长时间内需要高效并发地处理大批量数据的系统中,其对于GC的影响还是存在一定的区别。

6、执行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();//释放两把锁
        }
    }
           
void fullyLock() {
        putLock.lock();
        takeLock.lock();
    }

    void fullyUnlock() {
        takeLock.unlock();
        putLock.unlock();
    }
           

继续阅读