阻塞队列简介
BlockingQueue是继承自Queue的接口,在Queue的基础上增加了阻塞操作。想象一下,在阻塞队列没有出现之前,如果面对类似消费者-生产者的模型时,我们必须额外的实现同步策略以及线程间的唤醒策略,因此增加了不小的实现复杂度。当BlockingQueue出现之后,我们再也不需要关心什么时候需要阻塞线程,什么时候需要唤醒线程,因为这一切BlockingQueue都给我们实现了。简单来说,就是在BlockingQueue为空时从队头取数据将会被阻塞,当BlockingQueue有容量限制且满了,那么插入数据的线程将会阻塞。因此阻塞队列给我们提供了极大的方便性。
核心方法简介
添加数据方法
add(e):将元素添加到队列末尾,成功则返回true;如果队列已满,则插入失败,抛出异常。
offer(e):将元素添加到队列末尾,成功则返回true;如果队列已满,则插入失败,返回false。
put(e):将元素添加到队列末尾,如果队列已满,队列会一直阻塞生产者线程。
offer(e,time,unit):将元素添加到队列末尾,如果队列已满,则等待一定的时间,当时间期限达到时,如果还没有插入成功,则返回false;否则返回true。
获取数据方法
remove():删除队首元素,成功则返回true;如果队列为空,则删除失败,抛出异常。
poll():删除队首元素,若成功则返回则返回队首元素,若队列为空,则返回null。
take():从队首取元素,若队列为空,队列会一直阻塞消费者线程。
poll(time,unit):从队首取元素,如果队列为空,则等待一定的时间,当时间期限达到时,如果还没有取出元素,则返回null;否则返回队首元素。
常见阻塞队列
ArrayBlockingQueue:是一个用数组实现的有界阻塞队列,必须设置容量。并且可以指定公平性与非公平性,默认情况下为非公平的,即不保证等待时间最长的队列最优先能够访问队列,通常情况下为了保证公平性会降低吞吐量。
LinkedBlockingQueue:是一个用链表实现的有界阻塞队列,容量可以选择进行设置,不设置的话,将是一个无边界的阻塞队列,最大长度为Integer.MAX_VALUE。
ArrayBlockingQueue和LinkedBlockingQueue是两个最普通也是最常用的阻塞队列,一般情况下,在处理多线程间的生产者消费者问题,使用这两个类足以。
PriorityBlockingQueue:它会按照元素的优先级对元素进行排序,按照优先级顺序出队,每次出队的元素都是优先级最高的元素,是一个无界队列。
DelayQueue:一个支持延时获取元素的无界阻塞队列,DelayQueue中的元素只有当其指定的延迟时间到了,才能够从队列中获取到该元素。可以应用于缓存系统的设计和定时任务调度。
阻塞队列总结
并发编程中,一般推荐使用阻塞队列,不需要再单独考虑同步和线程间通信的问题。这篇文章只是对阻塞队列的初探,后续文章会深入研究各个阻塞队列的具体实现。