1 概述
- java.util.concurrent.BlockingQueue
队列是一种 FIFO(先进先出)的数据结构,本文要讲的 BlockingQueue 也是一种队列,而且强调了线程安全的特性。
BlockingQueue 是一个线程安全的队列接口,多个线程能够以并发的方式从队列中插入数据,取出数据的同时不会出现线程安全的问题。
2 生产者和消费者例子
BlockingQueue 通常用于消费者线程向队列存入数据,消费者线程从队列中取出数据,具体如下
- 生产者线程不停的向队列中插入数据,直到队列满了,生产者线程被阻塞
- 消费者线程不停的从队列中取出数据,直到队列为空,消费者线程被阻塞
3 BlockingQueue 方法
BlockingQueue 提供 4 种不同类型的方法用于插入数,取出数据以及检查数据,具体如下
1. 操作失败,抛出异常 | 2. 无论成功/失败,立即返回 true/false | 3. 如果队列为空/满,阻塞当前线程 | 4. 如果队列为空/满,阻塞当前线程并有超时机制 | |
---|---|---|---|---|
插入 | add(o) | offer(o) | put(o) | offer(o, timeout, timeunit) |
取出 | remove(o) | poll() | take() | poll(timeout, timeunit) |
检查 | element() | peek() |
4 BlockingQueue 的具体实现类
BlockingQueue 只是一个接口,在实际开发中有如下的类实现了该接口。
- ArrayBlockingQueue
- DelayQueue
- LinkedBlockingQueue
- PriorityBlockingQueue
- SynchronousQueue
5 ArrayBlockingQueue 的使用
这里以 BlockingQueue 接口的具体实现类 ArrayBlockingQueue 举例。通过 ArrayBlockingQueue 实现一个消费者和生产者多线程模型。
核心内容如下
- 以 ArrayBlockingQueue 作为生产者和消费者的数据容器
- 通过 ExecutorService 启动 3 个线程,2 两个生产者,1 个消费者
- 指定数据总量
5.1 生产者线程
- ArrayBlockingQueueProducer
1 |
|
5.2 消费者线程
- ArrayBlockingQueueConsumer
1 | import org.slf4j.Logger; |
5.3 测试
- TestBlockingQueue
1 | import com.ckjava.synchronizeds.appCache.WaitUtils; |
- 输出如下
1 | 13:54:17.884 [pool-1-thread-3] INFO c.c.b.ArrayBlockingQueueConsumer - thread pool-1-thread-3 consume task task_5 |