ArrayBlockingQueue和LinkedBlockingQueue的区别:
队列中锁的实现不同
ArrayBlockingQueue实现的队列中的锁是没有分离的,即生产和消费用的是同一个锁;
LinkedBlockingQueue实现的队列中的锁是分离的,即生产用的是putLock,消费是takeLock在生产或消费时操作不同
ArrayBlockingQueue实现的队列中在生产和消费的时候,是直接将枚举对象插入或移除的;
LinkedBlockingQueue实现的队列中在生产和消费的时候,需要把枚举对象转换为Node<E>进行插入或移除,会影响性能队列大小初始化方式不同
ArrayBlockingQueue实现的队列中必须指定队列的大小;
LinkedBlockingQueue实现的队列中可以不指定队列的大小,但是默认是Integer.MAX_VALUE
4.ArrayBlockingQueue采用的是数组,LinkedBlockingQueue采用的是单向链表
put take 实现原理:
里面有两个显式条件队列Condition 由ReentrantLock newConditon()得到
一个为notFull:没有满
另一个为notEmpty:不是空的
final Object[] items;缓冲队列
当put一个元素时先判断是不是满的如果是九调用notFull.await()阻塞到不是满的
添加成功之后调用notEmpty.singnal();通知消费者有产品可消费了,解除消费者阻塞
当take一个元素时先判断是不是空的如果是空的先调用notEmpty.await()阻塞,如果取得了元素(从items里面移除),就调用notFull.singnal()唤醒并阻塞的生产者。
一些主要方法
offer
将元素插入队列,成功返回true,如果当前没有可用的空间,则返回false
offer(E e, long timeout, TimeUnit unit)
将元素插入队列,在到达指定的等待时间前等待可用的空间
E poll(long timeout, TimeUnit unit)
获取并移除队列的头部,在指定的等待时间前等待可用的元素
E poll()
没有的话返回null
void put(E e)
将元素插入队列,将等待可用的空间(堵塞)
take()
获取并移除队列的头部,在元素变得可用之前一直等待(堵塞)
code
public static void main(String[] args){
//LinkedBlockingQueue<E>
BlockingQueue queue=new ArrayBlockingQueue(3);
for(int i=0;i<2;i++){
new Thread(){
public void run(){
while(true){
try{
Thread.sleep((long)Math.random()*1000);
System.out.println(Thread.currentThread().getName()+"准备放数据");
queue.put(1);
System.out.println(Thread.currentThread().getName()+"放了数据,队列目前有"+queue.size()+"个数据");
}
catch(Exception e){
e.printStackTrace();
}
}
}
}.start();
}
new Thread(){
public void run(){
while(true){
try{
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName()+"准备取数据");
queue.take();
System.out.println(Thread.currentThread().getName()+"取走一个数据,队列目前有"+queue.size()+"个数据");
}
catch(Exception e){
e.printStackTrace();
}
}
}
}.start();
}
运行结果: