LinkedBlockingQueue

LinkedBlockingQueue

介绍

可选有界阻塞队列基于链表,该队列遵循FIFO。存入队尾,取出队首。

使用

使用较简单就不介绍了。

源码解析

  • ReentrantLock+Condition原理

两个ReentrantLock两个Condition

	//取锁,控制取数据
    private final ReentrantLock takeLock = new ReentrantLock();
    //取等待,存唤醒
    private final Condition notEmpty = takeLock.newCondition();
    //存锁,控制存数据
    private final ReentrantLock putLock = new ReentrantLock();
    //存等待,取唤醒
    private final Condition notFull = putLock.newCondition();
  • offer(E e)

如果容量已满,则返回false,添加失败;如果是第一次添加则会唤醒一个等待中的取数据;如果添加数据中,还有容量则会以传播的形式唤醒等待中的存数据

	public boolean offer(E e) {
        if (e == null) throw new NullPointerException();
        final AtomicInteger count = this.count;
        //容量满,返回false
        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);
                //结点个数+1,但是c是原值
                c = count.getAndIncrement();
                //如果容量未满,因为存取使用的是各自独立的锁;所以如果出现数据存储,多次等待的情况下,取数据又取了多次(只有在容量边缘的时候才会唤醒一次),之后通过offer加了数据,这时候会以传播的形式唤醒剩余的等待,知道容量满了
                if (c + 1 < capacity)
                    notFull.signal();
            }
        } finally {
            putLock.unlock();
        }
        //如果数据是第一次存入,则会唤醒等待中的取数据操作
        if (c == 0)
            signalNotEmpty();
        return c >= 0;
    }
  • offer(E e, long timeout, TimeUnit unit)

和offer原理一样,唯一的区别是等待的时间是timeout,不是无限的

	public boolean offer(E e, long timeout, TimeUnit unit)
        throws InterruptedException {

        if (e == null) throw new NullPointerException();
        long nanos = unit.toNanos(timeout);
        int c = -1;
        final ReentrantLock putLock = this.putLock;
        final AtomicInteger count = this.count;
        putLock.lockInterruptibly();
        try {
            while (count.get() == capacity) {
                if (nanos <= 0)
                    return false;
                nanos = notFull.awaitNanos(nanos);
            }
            enqueue(new Node<E>(e));
            c = count.getAndIncrement();
            if (c + 1 < capacity)
                notFull.signal();
        } finally {
            putLock.unlock();
        }
        if (c == 0)
            signalNotEmpty();
        return true;
    }
  • put(E e)

和offer原理一样,唯一的区别是,如果容量已满,则put会等待

	public void put(E e) throws InterruptedException {
        if (e == null) throw new NullPointerException();
        int c = -1;
        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();
            }
            enqueue(node);
            c = count.getAndIncrement();
            if (c + 1 < capacity)
                notFull.signal();
        } finally {
            putLock.unlock();
        }
        if (c == 0)
            signalNotEmpty();
    }
  • poll()

取队尾数据,如果没有容量已满,则返回null;如果有数据,则取数据,并以传播的形式唤醒等待中的取数据,如果取数据刚好取的是边缘元素,则唤醒等待中的存数据

	public E poll() {
        final AtomicInteger count = this.count;
        if (count.get() == 0)
            return null;
        E x = null;
        int c = -1;
        final ReentrantLock takeLock = this.takeLock;
        takeLock.lock();
        try {
            if (count.get() > 0) {
                x = dequeue();
                c = count.getAndDecrement();
                //如果还有数据,则会以传播的形式唤醒等待中的取数据
                if (c > 1)
                    notEmpty.signal();
            }
        } finally {
            takeLock.unlock();
        }
        //如果是取的是边缘元素,则唤醒等待中的存数据
        if (c == capacity)
            signalNotFull();
        return x;
    }
  • take()

和poll原理一样,唯一的区别是如果没有数据take会等待,直到有数据;

	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();
            if (c > 1)
                notEmpty.signal();
        } finally {
            takeLock.unlock();
        }
        if (c == capacity)
            signalNotFull();
        return x;
    }
  • poll(long timeout, TimeUnit unit)

和poll原理一样,唯一的区别是等待的时间是timeout,不是无限的

	public E poll(long timeout, TimeUnit unit) throws InterruptedException {
        E x = null;
        int c = -1;
        long nanos = unit.toNanos(timeout);
        final AtomicInteger count = this.count;
        final ReentrantLock takeLock = this.takeLock;
        takeLock.lockInterruptibly();
        try {
            while (count.get() == 0) {
                if (nanos <= 0)
                    return null;
                nanos = notEmpty.awaitNanos(nanos);
            }
            x = dequeue();
            c = count.getAndDecrement();
            if (c > 1)
                notEmpty.signal();
        } finally {
            takeLock.unlock();
        }
        if (c == capacity)
            signalNotFull();
        return x;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

code_wang_hui

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值