详解LinkedBlockingQueue

来源:互联网 发布:数据的标准化的公式 编辑:程序博客网 时间:2024/06/07 05:35

LinkedBlockingQueue,许多书中称之为无界队列,那么他真的是无界队列吗?

从数据结构看,它是链表型的队列,链表的一个特性就是长度无限制,那LinkedBlockingQueue是不是跟链表一样长度无限制呢,答案是否定的,有长度限制。

     BlockingQueue<Object> bq1=new LinkedBlockingQueue<Object>(10000);     BlockingQueue<Object> bq2=new LinkedBlockingQueue<Object>();

创建队列的时候可以使用有参的构造函数,例子中bq1的长度为10000,那bq2使用无参的构造函数,是不是长度就是无限制了呢,咱们来看下构造函数:

    public LinkedBlockingQueue() {        this(Integer.MAX_VALUE);    }

无参构造函数内部调用的是有参的构造函数,设置了队列长度为Integer.MAX_VALUE。

    /** The capacity bound, or Integer.MAX_VALUE if none */    private final int capacity;    /** Current number of elements */    private final AtomicInteger count = new AtomicInteger();
capacity 是容量,而count则是当前队列中数据 的数量。

再看看常用的offer put poll跟take函数

先看offer函数

    public boolean offer(E e) {        if (e == null) throw new NullPointerException();        final AtomicInteger count = this.count;        if (count.get() == capacity)            return false;        int c = -1;        Node<E> node = new Node<E>(e);        final ReentrantLock putLock = this.putLock;        putLock.lock();        try {            if (count.get() < capacity) {                enqueue(node);                c = count.getAndIncrement();                if (c + 1 < capacity)                    notFull.signal();            }        } finally {            putLock.unlock();        }        if (c == 0)            signalNotEmpty();        return c >= 0;    }
插入的时候分为这么几步

1.判断当前的队列是否已满,如果满了直接return false。

2.然后将数据插入队列。

put函数呢

    public void put(E e) throws InterruptedException {        if (e == null) throw new NullPointerException();        // Note: convention in all put/take/etc is to preset local var        // holding count negative to indicate failure unless set.        int c = -1;        Node<E> node = new Node<E>(e);        final ReentrantLock putLock = this.putLock;        final AtomicInteger count = this.count;        putLock.lockInterruptibly();        try {            /*             * Note that count is used in wait guard even though it is             * not protected by lock. This works because count can             * only decrease at this point (all other puts are shut             * out by lock), and we (or some other waiting put) are             * signalled if it ever changes from capacity. Similarly             * for all other uses of count in other wait guards.             */            while (count.get() == capacity) {                notFull.await();            }            enqueue(node);            c = count.getAndIncrement();            if (c + 1 < capacity)                notFull.signal();        } finally {            putLock.unlock();        }        if (c == 0)            signalNotEmpty();    }
对比代码可以发现put函数跟offer有以下区别

1.锁使用的是lockInterruptibly这种可打断的锁

2.由于while()的存在,这个函数是一个阻塞函数,当队列满的时候put会阻塞。而offer则直接返回结果false了

而take跟poll与 put和offer函数的情况类似,具体大家可以看源码。

0 0
原创粉丝点击