当前位置: 代码迷 >> 综合 >> Java 集合 (18) -- 阻塞队列之 ArrayBlockingQueue 类
  详细解决方案

Java 集合 (18) -- 阻塞队列之 ArrayBlockingQueue 类

热度:70   发布时间:2023-12-16 13:18:37.0

文章目录

    • 1. 简介
    • 2. 继承体系
    • 3. 字段
    • 4. 构造器
    • 5. 常用方法

1. 简介

public class ArrayBlockingQueue<E> extends AbstractQueue<E>implements BlockingQueue<E>, java.io.Serializable {
    }

ArrayBlockingQueue 是 JUC 包下一个以数组实现的有界阻塞队列,它是线程安全的。它不需要扩容,因为它是初始化时指定容量并利用 takeIndex 和 putIndex 两个属性来实现数组的循环利用。

ArrayBlockingQueue 的缺点:

  1. 队列长度固定且必须在初始化时指定,所以使用之前一定要慎重考虑好容量;
  2. 如果消费速度跟不上入队速度,则会导致提供者线程一直阻塞,且越阻塞越多,非常危险;
  3. 只使用了一个锁来控制入队出队,效率较低,那是不是可以借助分段的思想把入队出队分裂成两个锁呢?答案是 LinkedBlockingQueue

2. 继承体系

在这里插入图片描述

3. 字段

// 使用数组存储元素
final Object[] items;// 取元素的指针,利用这个指针循环利用数组取出元素
int takeIndex;// 放元素的指针,利用这个指针循环利用数组存储元素
int putIndex;// 元素数量
int count;// 利用重入锁来保证并发安全
final ReentrantLock lock;// 非空条件
private final Condition notEmpty;// 非满条件
private final Condition notFull;

4. 构造器

  1. ArrayBlockingQueue 初始化时必须传入容量,也就是数组的大小
    public ArrayBlockingQueue(int capacity) {
          this(capacity, false);
    }
    
  2. 可以通过构造方法控制重入锁的类型是公平锁还是非公平锁
    public ArrayBlockingQueue(int capacity, boolean fair) {
          if (capacity <= 0)throw new IllegalArgumentException();// 初始化数组this.items = new Object[capacity];// 创建重入锁及两个条件lock = new ReentrantLock(fair);notEmpty = lock.newCondition();notFull =  lock.newCondition();
    }
    

5. 常用方法

  1. public boolean add(E e):add(e)时如果队列满了则抛出异常
  2. public boolean offer(E e):offer(e)时如果队列满了则返回false
  3. public void put(E e) throws InterruptedException:put(e)时如果队列满了则使用notFull等待
  4. public boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException:offer(e, timeout, unit)时如果队列满了则等待一段时间后如果队列依然满就返回false
  5. public E remove():remove()时如果队列为空则抛出异常
  6. public E poll():poll()时如果队列为空则返回null
  7. public E take() throws InterruptedException:take()时如果队列为空则阻塞等待在条件notEmpty上
  8. public E poll(long timeout, TimeUnit unit) throws InterruptedException:poll(timeout, unit)时如果队列为空则阻塞等待一段时间后如果还为空就返回null
  相关解决方案