多线程(十八、阻塞队列-ArrayBlockingQueue)
2020-12-13 05:11
标签:unlock obj xtend 成员 直接 this 条件队列 == code ArrayBlockingQueue方法一共4个:put(E e)、offer(e, time, unit)和take()、poll(time, unit),我们先来看插入元素的方法。 入队方法:enqueue 出队函数:dequeue 1、初始化: 2、插入元素“9” 3、插入元素“2”、“10”、“25”、“93” 4、插入元素“90” 注意,此时再插入一个元素“90”,则putIndex变成6,等于队列容量6,由于是循环队列,所以会将tableIndex重置为0。 重置代码看这里: 5、出队元素“9” 6、出队元素“2”、“10”、“25”、“93” 7、出队元素“90” 重置代码看这里 1、ArrayBlockingQueue利用了ReentrantLock来保证线程的安全性,针对队列的修改都需要加全局锁。 多线程(十八、阻塞队列-ArrayBlockingQueue) 标签:unlock obj xtend 成员 直接 this 条件队列 == code 原文地址:https://blog.51cto.com/janephp/24172701、队列的容量一旦在构造时指定,后续不能改变;
2、插入元素时,在队尾进行;删除元素时,在队首进行;
3、队列满时,插入元素会阻塞线程;队列空时,删除元素也会阻塞线程;
4、支持公平/非公平策略,默认为非公平策略。
ArrayBlockingQueue构造
核心构造方法:
/**
* 指定队列初始容量和公平/非公平策略的构造器.
*/
public ArrayBlockingQueue(int capacity, boolean fair) {
if (capacity
成员变量
public class ArrayBlockingQueue
方法
插入数据-put
/**
* 在队尾插入指定元素,如果队列已满,则阻塞线程.
*/
public void put(E e) throws InterruptedException {
checkNotNull(e);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly(); // 加锁
try {
while (count == items.length) // 队列已满。这里必须用while
notFull.await(); // 在notFull队列上等待
enqueue(e); // 队列未满, 直接入队
} finally {
lock.unlock();
}
}
/**
* 每次插入一个元素都会唤醒一个等待线程来处理
*/
private void enqueue(E x) {
final Object[] items = this.items;
items[putIndex] = x;
if (++putIndex == items.length) // 队列已满,则重置索引为0
putIndex = 0;
count++; // 元素个数+1
notEmpty.signal(); // 唤醒一个notEmpty上的等待线程(可以来队列取元素了)
}
删除元素-take
/**
* 从队首删除一个元素, 如果队列为空, 则阻塞线程
*/
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == 0) // 队列为空, 则线程在notEmpty条件队列等待
notEmpty.await();
return dequeue(); // 队列非空,则出队一个元素
} finally {
lock.unlock();
}
}
/**
*删除一个元素,则唤醒一个等待插入的线程
*/
private E dequeue() {
final Object[] items = this.items;
E x = (E) items[takeIndex];
items[takeIndex] = null;
if (++takeIndex == items.length) // 如果队列已空,重置获取索引
takeIndex = 0;
count--;
if (itrs != null)
itrs.elementDequeued();
notFull.signal(); // 唤醒一个notFull上的等待线程(可以插入元素到队列了)
return x;
}
环形结构
注意,此时再出队一个元素“90”,则tabeIndex变成6,等于队列容量6,由于是循环队列,所以会将tableIndex重置为0总结
2、ArrayBlockingQueue是有界的,且在初始时指定队列大小。
3、ArrayBlockingQueue的内部数组其实是一种环形结构。
文章标题:多线程(十八、阻塞队列-ArrayBlockingQueue)
文章链接:http://soscw.com/essay/30547.html