一、简介
ArrayBlockingQueue
是一个先进先出队列,维护takeIndex
和putIndex
两个指针,可循环使用数组。
- 线程安全
- 一定初始化数组后,数组长度就不能改变
(1)方法
方法 | 抛出异常 | 返回特殊值 | 阻塞 | 超时退出 |
---|---|---|---|---|
插入 | add() | offer() | put() | offer(e, time, unit) |
移除 | remove() | poll() | take() | poll(time, unit) |
二、源码分析
(1)put()
public void put(E e) throws InterruptedException {
checkNotNull(e);
final ReentrantLock lock = this.lock;
// 若线程中断,则抛异常
lock.lockInterruptibly();
try {
// 若队列满,则等待,加入`condition`队列
while (count == items.length)
notFull.await();
enqueue(e);
} finally {
lock.unlock();
}
}
(2)take()
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
// 若队列没有数据,则等待,加入`condition`队列
while (count == 0)
notEmpty.await();
return dequeue();
} finally {
lock.unlock();
}
}
三、应用场景
可用于 生产者消费者模型。
public class ArrayBlockingQueueTest {
private ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10);
public static void main(String[] args) {
ArrayBlockingQueueTest test = new ArrayBlockingQueueTest();
Consumer consumer = test.new Consumer();
Producer producer = test.new Producer();
consumer.start();
producer.start();
}
class Consumer extends Thread {
@Override
public void run() {
try {
Integer num = queue.take();
System.out.println(Thread.currentThread().getName() + " 拿到数字: " + num);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Producer extends Thread {
@Override
public void run() {
try {
int num = 1;
queue.put(num);
System.out.println(Thread.currentThread().getName() + " 放入数字: " + num);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
如图:
输出可能乱序