有界阻塞队列ArrayBlockingQueue和无界阻塞队列LinkedBlockingQueue

ArrayBlockingQueue和LinkedBlockingQueue最大的区别是一个是有界无界,各有优劣。

先看实例代码:

main函数起2个线程模拟生成消费者

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class BlockingQueueExample {
    public static void main(String[] args) throws Exception {

        BlockingQueue queue = new ArrayBlockingQueue(1024);
        //BlockingQueue queue = new LinkedBlockingQueue(1024);
        Producer producer = new Producer(queue);
        Consumer consumer = new Consumer(queue);

        new Thread(producer).start();
        new Thread(consumer).start();

        Thread.sleep(4000);
    }
}

生产者: 

public class Producer implements Runnable{

    protected BlockingQueue queue = null;

    public Producer(BlockingQueue queue) {
        this.queue = queue;
    }

    public void run() {
        try {
            queue.put("1>>> "+DateUtil.getNowTimeString());
            Thread.sleep(1000);
            queue.put("2>>> "+DateUtil.getNowTimeString());
            Thread.sleep(5000);
            queue.put("3>>> "+DateUtil.getNowTimeString());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

消费者: 

public class Consumer implements Runnable{

    protected BlockingQueue queue = null;

    public Consumer(BlockingQueue queue) {
        this.queue = queue;
    }

    public void run() {
        try {
            System.out.println(queue.take()+" "+DateUtil.getNowTimeString());
            System.out.println(queue.take()+" "+DateUtil.getNowTimeString());
            System.out.println(queue.take()+" "+DateUtil.getNowTimeString());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

数据量少的情况下LinkedBlockingQueue差别不大。

 

二者的类图:

LinkedBlockingQueue源码初始化默认不指定大小就使用Integer.MAX_VALUE配置的默认值:

/**
     * Creates a {@code LinkedBlockingQueue} with a capacity of
     * {@link Integer#MAX_VALUE}.
     */
    public LinkedBlockingQueue() {
        this(Integer.MAX_VALUE);
    }

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

 ArrayBlockingQueue生产者和消费者使用的是同一把锁ReentrantLock lock:

put: 

take: 

https://stackoverflow.com/questions/18375334/what-is-the-difference-between-arrayblockingqueue-and-linkedblockingqueue

https://stackoverflow.com/questions/35967792/when-to-prefer-linkedblockingqueue-over-arrayblockingqueue

 

关于二者的异同参考下面的这个总结的还不错:LinkedBlockingQueue和ArrayBlockingQueue的异同

相同:

LinkedBlockingQueue和ArrayBlockingQueue都是可阻塞的队列

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

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

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

不同:

1、锁机制不同

  LinkedBlockingQueue中的锁是分离的,生产者的锁PutLock,消费者的锁takeLock

  而ArrayBlockingQueue生产者和消费者使用的是同一把锁;

2、底层实现机制也不同

  LinkedBlockingQueue内部维护的是一个链表结构。

在生产和消费的时候,需要创建Node对象进行插入或移除,大批量数据的系统中,其对于GC的压力会比较大。

  而ArrayBlockingQueue内部维护了一个数组

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

3、构造时候的区别

  LinkedBlockingQueue有默认的容量大小为:Integer.MAX_VALUE,当然也可以传入指定的容量大小

ArrayBlockingQueue在初始化的时候,必须传入一个容量大小的值

4、执行clear()方法

  LinkedBlockingQueue执行clear方法时,会加上两把锁

 5、统计元素的个数

  LinkedBlockingQueue中使用了一个AtomicInteger对象来统计元素的个数,ArrayBlockingQueue则使用int类型来统计元素。

 

这个博客写的并发编程内容很全可以看看:http://tutorials.jenkov.com/java-concurrency/blocking-queues.html 

这个图画的很细,如果前面看不明白可以看看这个:深入剖析java并发之阻塞队列LinkedBlockingQueue与ArrayBlockingQueue

 

©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页
实付 9.90元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值