BlockingQueue实现类<二>

这篇文章主要讲LinkedBlockingQueue。阻塞队列使用链表来完成存储,之前分析的ArrayBlockingQueue是用数组。现在看下具体实现会有什么特点,还是从构造方法出发。

   public LinkedBlockingQueue(int capacity) {
        if (capacity <= 0) throw new IllegalArgumentException();
        this.capacity = capacity;
        //初始化了一个Node。
        last = head = new Node<E>(null);
    }

跟之前一样,来分析下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();
                //再加1,还小于容量,可以释放锁。
                if (c + 1 < capacity)
                    notFull.signal();
            }
        } finally {
            putLock.unlock();
        }
        if (c == 0)
            signalNotEmpty();
        return c >= 0;
    }

//将node 放在链尾的末端。

   private void enqueue(Node<E> node) {
        // assert putLock.isHeldByCurrentThread();
        // assert last.next == null;
        last = last.next = node;
    }

//获取head的内容。

public E take() throws InterruptedException {
        E x;
        int c = -1;
        final AtomicInteger count = this.count;
        //写锁。
        final ReentrantLock takeLock = this.takeLock;
        takeLock.lockInterruptibly();
        try {
        //没有内容,需要等待。
            while (count.get() == 0) {
                notEmpty.await();
            }
            x = dequeue();
            c = count.getAndDecrement();
            //释放notEmpty锁。
            if (c > 1)
                notEmpty.signal();
        } finally {
            takeLock.unlock();
        }
        if (c == capacity)
            signalNotFull();
        return x;
    }

来分析下 dequeue()。链表操作。返回了head结点并且head置为空,释放掉。注意写法很考究。

private E dequeue() {
        // assert takeLock.isHeldByCurrentThread();
        // assert head.item == null;
        Node<E> h = head;
        Node<E> first = h.next;
        //这样原来的头部结点的next也指向自身了。原来next持有别的对象,这样容易gc释放。
        h.next = h; // help GC
        //head变为了原来的next。
        head = first;
        E x = first.item;
        first.item = null;
        return x;
    }

其实跟之前分析的ArrayBlockingQueue差别不大。不过是读写分离,利用链表实现。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值