JUC高并发:线程池中的ArrayBlockingQueue和LinkedBlockingQueue

线程池的阻塞队列有多种实现可选,这里仅介绍ArrayBlockingQueue和LinkedBlockingQueue(鼓励大家多看源码的一些注释,讲的很清楚)

目录

ArrayBlockingQueue

LinkedBlockingQueue

ArrayBlockingQueue部分源码

LinkedBlockingQueue部分源码


ArrayBlockingQueue

  • 有界,在创建的时候指定了大小,创建后,大小不可再更改
  • 底层通过object数组存储
  • 采用FIFO机制
  • 队头是等待最久的任务,新任务加入阻塞队列的时候采用尾插法
  • 内部结合一个ReetrantLock(取和放共用一个锁,所以取的时候没法放,放的时候没法取,吞吐量降低(相对LinkedBlockingQueue而言))和两个Condition使用,notEmpty条件用于从队列中取出一个任务,notFull条件表明可以将任务放入阻塞队列
  • 构建ArrayBlockingQueue的时候,可以指定ReetrantLock是公平锁还是非公平锁

LinkedBlockingQueue

  • 底层通过单链表实现
  • 无界,因为是链表结构
  • 默认最长长度是Integer.MAX_VALUE,可以通过构造函数来指定最长长度
  • 采用FIFO机制
  • 队头是等待最久的任务,新任务加入阻塞队列的时候采用尾插法
  • 链接队列通常比基于数组的队列具有更高的吞吐量(吞吐量是指系统在单位时间内处理请求的数量,因为取操作和放操作采用了两个不同的锁,所以两个操作可以并行),但是在大多数并发应用程序中,可预测性能较差。
  • 内部有两个ReetrantLock(takeLock,putLock)和两个Condition(notEmpty,notFull)

ArrayBlockingQueue部分源码

    // 采用put时,如果队列满了,就阻塞等待,直到有空间可用
    public void put(E e) throws InterruptedException {
        checkNotNull(e);
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == items.length)
                // 满了,一直等待
                notFull.await();
            enqueue(e);
        } finally {
            lock.unlock();
        }
    }
    
    // 尾插法插入,如果满了,就不插入,返回false,不满则插入,返回true
    public boolean offer(E e) {
        checkNotNull(e);
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            if (count == items.length)
                return false;
            else {
                enqueue(e);
                return true;
            }
        } finally {
            lock.unlock();
        }
    }

    public E poll() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            return (count == 0) ? null : dequeue();
        } finally {
            lock.unlock();
        }
    }

    public E take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == 0)
                notEmpty.await();
            return dequeue();
        } finally {
            lock.unlock();
        }
    }

LinkedBlockingQueue部分源码

    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 {
            while (count.get() == capacity) {
                notFull.await();
            }
            enqueue(node);
            c = count.getAndIncrement();
            if (c + 1 < capacity)
                notFull.signal();
        } finally {
            putLock.unlock();
        }
        if (c == 0)
            signalNotEmpty();
    }

    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;
    }

    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;
    }

    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;
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

进击的Coder*

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

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

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

打赏作者

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

抵扣说明:

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

余额充值