![](https://cdn.zimug.com/wx-zimug.png)
类`ArrayBlockingQueue`是`BlockingQueue`接口的实现类,它是**有界的**阻塞队列,**内部使用数组存储队列元素**。这里的“有界”是指存储容量存在上限,不能无限存储元素。在同一时间内存储容量存在着一个上限值,这个上限制在初始实例化的时候指定,之后便不能修改了。
`ArrayBlockingQueue`内部采用FIFO (First In, First Out)先进先出的方法实现队列数据的存取,队首的元素是在队列中保存时间最长的元素对象,队尾的元素是在队列中保存时间最短的元素对象。
下面的代码说明如何初始化一个`ArrayBlockingQueue`,并向其中添加一个对象:
~~~
BlockingQueue queue = new ArrayBlockingQueue(1024);
queue.put("1"); //向队列中添加元素
Object object = queue.take(); //从队列中取出元素
~~~
`BlockingQueue`可以通过泛型来限定队列中存储数据的类型,下面的代码以String为泛型,表示该队列只能存储String类型。
~~~
BlockingQueue<String> queue = new ArrayBlockingQueue<String>(1024);
queue.put("1");
String string = queue.take();
~~~
## 实现一个生产消费的实例
在前面的文章中我们曾经讲过:BlockingQueue经常被用于生产消费的缓冲队列。下面我们就使用`ArrayBlockingQueue`来真正的实现一个生产消费的例子。
类`BlockingQueueExample`开启两个独立线程,一个是`Producer`生产者线程,负责向队列中添加数据;另一个是`Consumer`消费者线程,负责从队列中取出数据进行处理。
~~~
public class BlockingQueueExample {
public static void main(String[] args) throws Exception {
//使用ArrayBlockingQueue初始化一个BlockingQueue,指定容量的上限为1024
BlockingQueue queue = new ArrayBlockingQueue(1024);
Producer producer = new Producer(queue); //生产者
Consumer consumer = new Consumer(queue); //消费者
new Thread(producer).start(); //开启生产者线程
new Thread(consumer).start(); //开启消费者线程
Thread.sleep(4000);
}
}
~~~
类`Producer`为生产者,每隔10秒钟使用`put()`方法向队列中放入一个对象,放入三次。在这10秒的间隔内,队列数据被消费者取走之后将导致消费者线程阻塞。
~~~
public class Producer implements Runnable{
protected BlockingQueue queue = null;
public Producer(BlockingQueue queue) {
this.queue = queue;
}
public void run() {
try {
queue.put("1");
Thread.sleep(10000);
queue.put("2");
Thread.sleep(10000);
queue.put("3");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
~~~
下面的代码是消费者类`Consumer`,它从队列中获取待处理的元素对象,并调用`System.out`将其打印出来。
~~~
public class Consumer implements Runnable{
protected BlockingQueue queue = null;
public Consumer(BlockingQueue queue) {
this.queue = queue;
}
public void run() {
try {
System.out.println(queue.take());
System.out.println(queue.take());
System.out.println(queue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
~~~
上面的代码打印结果是每隔10秒打印一次,因为其中`take()`方法在队列内没有元素可以取到的时候,会阻塞当前的消费者线程,让其处于等待状态,这个方法我们在上一节介绍`BlockingQueue`的时候就已经进行过说明。
- 线程
- 1.进程和线程-锁与信号量
- 2.Thread类线程状态转换
- 2.并发与并行-同步与异步
- 4.线程池
- 5.对象级别与类级别的同步锁
- 6.创建线程的四种方式
- 7.临界区-阻塞-活锁-死锁
- 2.JMM多线程模型
- JUC
- BlockingQueue
- ArrayBlockingQueue
- DelayQueue
- LinkedBlockingQueue
- PriorityBlockingQueue
- SynchronousQueue
- BlockingDeque
- ConcurrentHashMap
- CountDownLatch
- CyclicBarrier
- Exchanger
- AtomicInteger
- Lock
- Condition
- ReentrantLock读写锁
- StampedLock
- Semaphore