BlockingQueue 阻塞队列的顶层接口
先来解释下,阻塞队列是什么,是干什么用的,阻塞通俗点讲就是堵住了进不去,在Java中阻塞是多线程运行程序,一条线程带着锁进去执行了,其他后来的线程就无法获取锁,只能等待执行,就是阻塞.阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空。当队列满时,存储元素的线程会等待队列可用。阻塞队列常用于生产者和消费者的场景,生产者是往队列里添加元素的线程,消费者是从队列里拿元素的线程。阻塞队列就是生产者存放元素的容器,而消费者也只从容器里拿元素。
阻塞队列常用的三种实现类
队列 | 有界性(长度) | 锁 | 数据结构 |
ArrayBlockingQueue | bounded(有界) | 加锁 | arrayList |
LinkedBlockingQueue | optionally-bounded | 加锁 | linkedList |
SynchronousQueue | bounded | 加锁 | 无 |
常用实现类队列特点
-
ArrayBlockingQueue:是一个用数组实现的有界阻塞队列,此队列按照先进先出(FIFO)的原则对元素进行排序。支持公平锁和非公平锁。【注:每一个线程在获取锁的时候可能都会排队等待,如果在等待时间上,先获取锁的线程的请求一定先被满足,那么这个锁就是公平的。反之,这个锁就是不公平的。公平的获取锁,也就是当前等待时间最长的线程先获取锁】
-
LinkedBlockingQueue:一个由链表结构组成的有界队列,此队列的长度为Integer.MAX_VALUE。此队列按照先进先出的顺序进行排序。
-
SynchronousQueue: 一个不存储元素的阻塞队列,每一个put操作必须等待take操作,否则不能添加元素。支持公平锁和非公平锁。
常用方法
boolean add(E e) 添加元素 满了抛异常
boolean offer(E e) 添加元素 满了不抛异常 返回false
public void put(E e) 添加元素,队列满了,则等待
E poll(long timeout, TimeUnit unit) 在指定时间后移除元素(队列头部)
public E take() 移除队列头部的元素
三种队列方法的代码
public class Test {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// BlockingQueue<Integer> blockingQueue = new ArrayBlockingQueue<>(5);
// BlockingQueue<Integer> blockingQueue = new LinkedBlockingQueue<>();
BlockingQueue<Integer> blockingQueue = new SynchronousQueue<>();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 1; i <= 5; i++) {
try {
blockingQueue.put(i);
System.out.println("存入数据-->"+i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while(true){
try {
Thread.sleep(1000);
System.out.println("取出数据-->"+blockingQueue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
运行结果
ArrayBlockingQueue
LinkedBlockingQueue
SynchronousQueue
运行结果可以看出三种阻塞队列的特点.