详解LinkedBlockingQueue

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值