JAVA并发学习-ArrayBlockingQueue LinkedBlockingQueue

ArrayBlockingQueue和LinkedBlockingQueue的区别:

  1. 队列中锁的实现不同
    ArrayBlockingQueue实现的队列中的锁是没有分离的,即生产和消费用的是同一个锁;
    LinkedBlockingQueue实现的队列中的锁是分离的,即生产用的是putLock,消费是takeLock

  2. 在生产或消费时操作不同
    ArrayBlockingQueue实现的队列中在生产和消费的时候,是直接将枚举对象插入或移除的;
    LinkedBlockingQueue实现的队列中在生产和消费的时候,需要把枚举对象转换为Node进行插入或移除,会影响性能

  3. 队列大小初始化方式不同
    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
    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();
}

运行结果:

JAVA并发学习-ArrayBlockingQueue LinkedBlockingQueue_第1张图片
图片.png

你可能感兴趣的:(JAVA并发学习-ArrayBlockingQueue LinkedBlockingQueue)