ArrayBlockingQueue
底层基于数组,具有阻塞的功能,FIFO,生产消费者模式
Queue提供的api
add,offer 插入元素
remove,poll 取元素
element,peek 查询元素
抛异常 阻塞 超时 返回特殊值(一般情况都是boolean,null)
插入元素(遇到慢的情况) add put offer offer
取元素(删除取出的元素) remove take poll poll
查询元素(对队列没有影响) element peek
ArrayBlockingQueue结构
items
存放元素
takeIndex
取元素的指针,记录下一次出队的位置
putIndex
存元素的指针,记录下一次入队的位置 (指向下一个空位置)
两个指针可以形成一个环形数组,take追着put跑,当put到数组的最大值的时候会将putIndex指向下标为0的节点,takeIndex也是从下标为0的节点开始处理,这样会重复利用数组的节点,当takeIndex==putIndex说明元素被取空了或者满了
count
计算元素个数
ReentrantLook
ArrayBlockingQueue中维护了一把锁,入队和出队是相互阻塞的
Condition
有两个Condition是通过ReentrantLook来获取的,这里使用到await和signal,lock.newCondition返回的对象await必须要用同一个对象signal唤醒
notEmpty 出队的对象,说明队列不为空,唤醒的是take
notFull 入队的对象,说明队列
使用
@Service
public class ArrayBlockingQueueTest {
private static ArrayBlockingQueue<String> arrayBlockingQueue = new ArrayBlockingQueue<>(10);
@Scheduled(cron="0/5 * * * * ? ")
public void test(){
//放数据
try {
arrayBlockingQueue.put(new Date().toString());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@PostConstruct
public void init(){
new Thread(() -> {
while (true){
try {
// 取数据
String take = arrayBlockingQueue.take();
System.out.println("拿到数据" + take);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("执行");
}
}).start();
}
}