Java并发学习笔记(七)-ArrayBlockingQueue
来源:互联网 发布:淘宝试用如何领取 编辑:程序博客网 时间:2024/06/05 07:57
Java并发包concurrent里提供了3个阻塞队列,ArrayBlockingQueue,LinkedBlockingQueue,PriorityBlockingQueue。阻塞队列通常用于生产消费模式,满队列时生产者阻塞,空队列时消费者阻塞。ArrayBlockingQueue是一个有界的阻塞队列,此队列按FIFO原则增加删除元素。底层实现是一个数组。
public class ArrayBlockingQueueDemo {public static void main(String[] args) {ExecutorService es = Executors.newCachedThreadPool();BlockingQueue<Bread> queue = new ArrayBlockingQueue<Bread>(10);for (int i = 0; i < 2; i++) {es.execute(new Baker(queue));}for (int i = 0; i < 10; i++) {es.execute(new BreadConsumer(queue));}es.shutdown();}}class Baker implements Runnable {private static int no = 0;private int id = ++no;private int count = 0;private BlockingQueue<Bread> queue;public Baker(BlockingQueue<Bread> queue) {this.queue = queue;}@Overridepublic void run() {for (int i = 0; i < 10; i++) {System.out.println("面包师" + id + "正准备做第" + ++count + "面包");Bread bread = new Bread();// 满队列情况下,阻塞try {queue.put(bread);System.out.println("面包师" + id + "做的第" + count + "面包是面包"+ bread.getId());} catch (InterruptedException e) {}}}}class BreadConsumer implements Runnable {private static int no = 0;private int id = ++no;private int count = 0;private BlockingQueue<Bread> queue;public BreadConsumer(BlockingQueue<Bread> queue) {this.queue = queue;}@Overridepublic void run() {for (int i = 0; i < 2; i++) {System.out.println("顾客 " + id + "准备买第" + ++count + "个面包");// 空队列情况下,阻塞try {Bread bread = queue.take();System.out.println("顾客" + id + "买到的第" + count + "个面包是面包"+ bread.getId());} catch (InterruptedException e) {}}}}class Bread {private static int count = 0;private int id = ++count;public int getId() {return id;}}
该类也提供了其它一些非阻塞的方法,如add,offer,pull等。看看它的实现。
构造函数
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(); }capacity是初始化时数组长度,fair是表示是否为公平锁(这里不介绍这个)。我们可以看到,在构造函数里,有一个Object数组,保存队列元素,有两个lock的condition,分别表示非空队列条件及非满队列条件。
再看阻塞插入方法put
public void put(E e) throws InterruptedException { checkNotNull(e); final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { while (count == items.length) notFull.await(); insert(e); } finally { lock.unlock(); } }
正式插入元素之前,使用可中断的lock锁。count表示当前队列里的元素个数。如果队列元素个数等于数组长度,那么非满队列条件阻塞,等待队列非满时唤醒。如果队列不满,则插入。
private void insert(E x) { items[putIndex] = x; putIndex = inc(putIndex); ++count; notEmpty.signal(); }insert方法,在队列尾部插入一个元素,重新对putIndex计算,队列元素个数加1,并在最后唤醒非空队列条件,表示可以从队列中取出元素。
再来看阻塞方法take
public E take() throws InterruptedException { final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { while (count == 0) notEmpty.await(); return extract(); } finally { lock.unlock(); } }与put类似,获取锁,再判断队列是否为空,空队列,则非空队列条件等待,刚才的insert方法在插入一个元素后,会唤醒这个条件。如果队列不为空,则取出一个元素。
private E extract() { final Object[] items = this.items; E x = this.<E>cast(items[takeIndex]); items[takeIndex] = null; takeIndex = inc(takeIndex); --count; notFull.signal(); return x; }extract方法从队列头部读取一个元素,并置数组中该元素为null,防止内存泄露,队列元素个数减1,并唤醒非满队列条件,说明已经不是满队列,可以插入元素了。
offer和pull的实现也比较相似,只是没有阻塞这个动作
public E poll() { final ReentrantLock lock = this.lock; lock.lock(); try { return (count == 0) ? null : extract(); } finally { lock.unlock(); } }
我们在insert和extract里看到inc(int)方法。
final int inc(int i) { return (++i == items.length) ? 0 : i; }如果当前索引等于数组长度,则置为0,不然不变,可以看出来,这里的数组作为队列的容器,是循环使用的。
0 0
- Java并发学习笔记(七)-ArrayBlockingQueue
- Java并发----ArrayBlockingQueue
- java高并发程序设计学习笔记七并发设计模式
- ArrayBlockingQueue学习笔记
- java并发编程(13)--ArrayBlockingQueue
- Java并发容器之ArrayBlockingQueue
- java 并发工具包 BlockingQueue-ArrayBlockingQueue
- 《JAVA并发编程实践》学习笔记(第六.七章)
- [学习笔记] Java核心技术 卷一:基础知识 并发(七)
- Java 7之多线程并发容器 - ArrayBlockingQueue
- (十五)java多线程之并发集合ArrayBlockingQueue
- java并发编程-同步类容器-ArrayBlockingQueue
- java学习笔记(七)
- Java学习笔记七
- Java并发学习笔记
- java并发学习笔记
- [Java并发包学习七]解密ThreadLocal
- [Java并发包学习七]解密ThreadLocal
- 查找页面控件
- Contingency and Management Reserve
- 更新字典(Updating a Dictionary)
- oracle的linesize名令
- linux下有关用户、组以及权限的学习
- Java并发学习笔记(七)-ArrayBlockingQueue
- Copy List with Random Pointer
- HttpRuntime的认识与加深理解
- 算法入门->插入排序->C/C++ 语言实现
- 读《大道至简-软件工程实践者的思想》
- 胜利大逃亡(续)(状态压缩+三维BFS)
- 内部类详解
- ES学习笔记2-理论进阶篇1
- linux 基础