1. 什么是阻塞队列?
- 当队列是空的,从队列中获取元素的操作将会被阻塞
- 当队列是满的,从队列中添加元素的操作将会被阻塞
- 试图从空的队列中获取元素的线程将会被阻塞,直到其他线程往空的队列插入新的元素
- 试图向已满的队列中添加新元素的线程将会被阻塞,直到其他线程从队列中移除一个或多个元素或者完全清空,使队列变得空闲起来并后续新增
2. 阻塞队列的分类
- ArrayBlockingQueue(常用):由数组结构组成的有界阻塞队列。
- LinkedBlockingQueue(常用):由链表结构组成的有界(但大小默认值为integer.MAX_VALUE)阻塞队列。
- DelayQueue:使用优先级队列实现的延迟无界阻塞队列,大小没有限制。
- PriorityBlockingQueue:支持优先级排序的队列。
- SynchronousQueue:不存储元素的阻塞队列,也就是单个元素的队列。
- LinkedTransferQueue:由链表组成的无界的阻塞的队列。
- LinkedBlockingDeque:由链表组成的双向的阻塞的队列。
3. 阻塞队列中的核心方法
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
public class BlockingQueueDemo {
public static void main(String[] args) throws InterruptedException {
//创建一个阻塞队列,定义大小为3
BlockingQueue<String> arrayBlockingQueue = new ArrayBlockingQueue<String>(3);
//第一组方法
System.out.println(arrayBlockingQueue.add("a"));//true
System.out.println(arrayBlockingQueue.add("b"));//true
System.out.println(arrayBlockingQueue.add("c"));//true
System.out.println(arrayBlockingQueue.element());//检查队头元素,但是不取出
// System.out.println(arrayBlockingQueue.add("d"));//异常:Queue full
//取出
System.out.println(arrayBlockingQueue.remove());//a
System.out.println(arrayBlockingQueue.remove());//b
System.out.println(arrayBlockingQueue.remove());//c
// System.out.println(arrayBlockingQueue.remove());//异常:NoSuchElementException
//第二组方法
//添加
System.out.println(arrayBlockingQueue.offer("a"));//true
System.out.println(arrayBlockingQueue.offer("b"));//true
System.out.println(arrayBlockingQueue.offer("c"));//true
System.out.println(arrayBlockingQueue.offer("d"));//false
//取出
System.out.println(arrayBlockingQueue.poll());//a
System.out.println(arrayBlockingQueue.poll());//b
System.out.println(arrayBlockingQueue.poll());//c
System.out.println(arrayBlockingQueue.poll());//null
//第三组方法
//添加
arrayBlockingQueue.put("a");
arrayBlockingQueue.put("b");
arrayBlockingQueue.put("c");
// arrayBlockingQueue.put("d");//阻塞,因为已经满了,需要取释放空间才可以继续
//取出
System.out.println(arrayBlockingQueue.take());
System.out.println(arrayBlockingQueue.take());
System.out.println(arrayBlockingQueue.take());
// System.out.println(arrayBlockingQueue.take());//阻塞,因为已经空了,需要取放入元素才可以继续
//第四组
arrayBlockingQueue.offer("a");
arrayBlockingQueue.offer("b");
arrayBlockingQueue.offer("c");
arrayBlockingQueue.offer("d",3L, TimeUnit.SECONDS);//空间满了阻塞,超过三秒还没放进去将不再阻塞,也不会添加
//取出
System.out.println(arrayBlockingQueue.poll());
System.out.println(arrayBlockingQueue.poll());
System.out.println(arrayBlockingQueue.poll());
System.out.println( arrayBlockingQueue.poll(3, TimeUnit.SECONDS));//null,阻塞3秒后此方法继续执行,不再阻塞
}
}