阻塞队列学习

本文详细介绍了阻塞队列的概念、在生产者-消费者模型中的作用,以及Java中提供的几种常见阻塞队列类型,包括它们的方法和源码分析。
摘要由CSDN通过智能技术生成
1、什么是阻塞队列?

顾名思义,就是支持阻塞的队列,相比于其他的队列,阻塞队列支持以下特性:

  • 队列为空的时候,获取元素的线程会等待队列变为非空。
  • 队列为满的时候,存储元素的线程会等待队列可以放入元素。
2、阻塞队列的用处?

通常用于生产者-消费者模型,可以起到解耦,削峰填谷的作用

3、java中的阻塞队列

JDK7提供了7个阻塞队列。分别是

  • ArrayBlockingQueue : 一个由数组结构组成的有界阻塞队列。
  • LinkedBlockingQueue : 一个由链表结构组成的有界阻塞队列。
  • PriorityBlockingQueue : 一个支持优先级排序的无界阻塞队列。
  • DelayQueue: 一个使用优先级队列实现的无界阻塞队列。
  • SynchronousQueue: 一个不存储元素的阻塞队列。
  • LinkedTransferQueue: 一个由链表结构组成的无界阻塞队列。
  • LinkedBlockingDeque: 一个由链表结构组成的双向阻塞队列。
4、介绍一些阻塞队列中常用的方法
  1. 添加元素的方法
    1. offer(E e):添加元素,不涉及阻塞
    2. offer(E e, long timeout, TimeUnit unit):带时间参数的offer,如果队列满了,会阻塞指定时间进行尝试添加,超时才会返回false
    3. put(E e) : 如果没办法添加到队列中,就会一直阻塞下去
  2. 取出元素的方法(取出并移除):
    1. poll() :取出元素,取不到就返回null
    2. poll(long timeout, TimeUnit unit) :取出元素,取不到就等待,指定时间后还取不到才会退出
    3. take():如果取不到元素,就一直阻塞下去

5、 源码,这里只介绍ArrayBlockingQueue,其他的也大同小异
5.1、基本属性和构造器
// 底层实现,数组
final Object[] items;
// 队列头部的索引坐标,因为是FIFO,用于take poll peek get等方法
int takeIndex;

// 队列尾部的索引坐标,用于offer,put add等方法
int putIndex;

// 记录队列中元素的个数
int count;

// 锁,默认非公平锁
final ReentrantLock lock;

// 定义两个条件对象,分别表示队列不为空,或者队列不为满
private final Condition notEmpty;
private final Condition notFull;

// 构造方法,默认使用费公平锁,也可以传入参数,选择公平锁
public ArrayBlockingQueue(int capacity) {
    this(capacity, false);
}

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.2 、添加元素方法
5.2.1 、add 方法其实最终调用的也是offer方法,就是添加元素,不涉及阻塞

5.2.2、 不带时间参数的offer

看上述代码,先加锁,如果数组元素满了,添加失败,返回false,否则添加成功,返回true。

5.2.3、带时间参数的offer

看代码,如如果队列满了,就await指定时间,指定时间内没有成功添加的话,返回false

5.2.4 put 方法

看代码,如果队列是满的添加不进去,该方法会一直阻塞

5.3 、取出元素方法
5.3.1 不带时间参数的poll

如果为空,就返回null,不为空就取出队列头部元素

5.3.2 带时间参数的poll

如果为空,等待指定时间,指定时间后还取不到元素,就返回null 

5.3.3 take方法

如果取不到元素,就一直阻塞下去。

5.4、enqueue 和 dequeue

enqueue,将元素添加到数组中的具体方法

  1. 将元素插入数组的指定坐标
  2. 如果当前坐标已经是数组元素的最后一位了,那么下一位坐标要从0开始,类似一个环形数组
  3. 当前元素树加1
  4. 激活因为队列为空而阻塞的线程。

dequeue, 将元素从数组中取出的具体方法

  1. 获取队头的元素,然后指定坐标位置元素置为null
  2. 如果当前坐标已经是数组元素的最后一位了,那么下一位坐标要从0开始,类似一个环形数组
  3. 当前元素数量减一
  4. 激活因为队列满了而阻塞的线程

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值