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