目录
阻塞队列(BlockingQueue)是一种特殊的队列,遵循 "先进先出" 的原则,它有两个特点:1. 队列为空时等待获取元素。2. 队列已满时等待插入元素的操作。具体来说,当一个线程试图从空的阻塞队列中获取元素时,该线程将被阻塞,直到队列中有可用元素为止。同样地,当一个线程试图向已满的阻塞队列中插入元素时,该线程将被阻塞,直到队列中有空闲位置为止。
阻塞队列通常用于实现生产者-消费者模式,其中生产者线程将数据放入队列,而消费者线程从队列中取出数据进行处理。那么这么做有什么好处呢?
标准库中提供了一个BlockingQueue的接口,它继承了Queue类,所以它包含Queue的所有方法,常见的阻塞队列实现包括ArrayBlockingQueue、LinkedBlockingQueue等。我们通常使用这些类中的 put() 和 take() 方法,因为其他的方法不具备 "阻塞" 特性。
- import java.util.concurrent.*;
- public class Demo {
- public static void main(String[] args) throws InterruptedException {
- BlockingQueue
blockingQueue = new LinkedBlockingQueue<>(); - blockingQueue.put("111");
- String t = blockingQueue.take();
- }
- }
这里我们使用循环数组的方式来实现阻塞队列。
- public class MyBlockingQueue {
- private int[] arr = new int[10];//队列
- //防止出现内存可见性的问题
- private volatile int head;//头
- private volatile int tail;//尾
- private volatile int size;//已经存了几个元素
- public MyBlockingQueue(){
- head = 0;
- tail = 0;
- size = 0;
- }
- public void put(int val) throws InterruptedException {
- synchronized (this){
- if(size == arr.length){
- this.wait();//队列满了,阻塞
- }
- arr[tail] = val;
- tail = (tail+1)%arr.length;
- size++;
- this.notify();//唤醒take()中的wait()
- }
- }
- public int take() throws InterruptedException {
- synchronized (this) {
- if(size == 0){
- this.wait();//队列为空,阻塞
- }
- int tmp = arr[head];
- head = (head+1)%arr.length;
- size--;
- this.notify();//唤醒put()中的wait()
- return tmp;
- }
- }
- }