LinedBlockingQueue 源码解析

构造方法

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

空参构造方法,也就是说没有传入大小,队列的大小默认为Integer的最大值

属性

	 private final int capacity;//容量
 
    private final AtomicInteger count = new AtomicInteger();//存储的元素个数
    transient Node<E> head;
    private transient Node<E> last;

    private final ReentrantLock takeLock = new ReentrantLock();

    private final Condition notEmpty = takeLock.newCondition();

    private final ReentrantLock putLock = new ReentrantLock();

    private final Condition notFull = putLock.newCondition();

对于LinedBlockingQueue 存储数据不在是基于数组,而是基于Node 节点组成的链表
同时使用了两把锁,和两个 Condition ,这就说明相对于ArrayBlockingQueue,LinedBlockingQueue 的并发度更高,因为支持两把锁

put()

public void put(E e) throws InterruptedException {
        if (e == null) throw new NullPointerException();
        int c = -1;
        // 当put一个元素的时候,先将这个元素封装为一个Node节点
        Node<E> node = new Node<E>(e);
        final ReentrantLock putLock = this.putLock;
        final AtomicInteger count = this.count;
       	// 上锁,添加元素的锁
        putLock.lockInterruptibly();
        try {    
        	//如果元素个数 == 最大容量,阻塞当前线程
            while (count.get() == capacity) {
                notFull.await();
            }
            //添加node
            enqueue(node);
            
            c = count.getAndIncrement();
            if (c + 1 < capacity)//如果c+1 小于最大容量
                notFull.signal();//唤醒等待put()的线程
        } finally {
            putLock.unlock();
        }
        if (c == 0)
            signalNotEmpty();
    }

take()

	public E take() throws InterruptedException {
        E x;
        int c = -1;
        //获取当前队列的元素个数
        final AtomicInteger count = this.count;
        final ReentrantLock takeLock = this.takeLock;
        //上take对应的锁
        takeLock.lockInterruptibly();
        try {
        	//如果队列里面一个元素也没有,阻塞当前队列
            while (count.get() == 0) {
                notEmpty.await();
            }
            //将当前元素移除队列
            x = dequeue();
            //队列元素个数--
            c = count.getAndDecrement();
            if (c > 1)//如果队列还有元素,唤醒阻塞的take()线程
                notEmpty.signal();
        } finally {
            takeLock.unlock();
        }
        if (c == capacity)
            signalNotFull();
        return x;
    }

总结

LinedBlockingQueue 相比ArrayBrockingQueue 并发度更高,因为支持两把锁
LinedBlockingQueue 其实也是一个有界队列,只是如果没有传入大小,队列默认的大小为Integer的最大值

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值