阻塞队列 当队列里面没有值时,会阻塞直到有值输入。当队列满的时候,会阻塞输入,直到队列有值输出
一,自己实现阻塞队列
生产者消费者模型
生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
这个阻塞队列就是用来给生产者和消费者解耦的。
public class MyBlockingQueue<T> {
private Object[] table;//维护一个定长数组;
private int takeIndex;//取出元素时的位置;
private int putIndex;//输入元素的位置
private int size;//数组内 数据长度
public MyBlockingQueue (int capacity){
table=new Object[capacity];//初始化数组长度
}
//添加元素
private synchronized void put (T type) throws InterruptedException {
while(size==table.length){//数据满了
wait ();
}
table[putIndex]=type;
putIndex=(putIndex+1)%table.length;
size++;
notifyAll();
}
//取元素
private synchronized T take() throws InterruptedException {
while(size==0){//数组内无元素
wait();
}
Object t=table[takeIndex];
takeIndex=(takeIndex+1)%table.length;
size--;
notifyAll();
return (T)t;
}
private synchronized int getSize(){
return size;
}
//生产者,存元素
public static void main(String[] args) {
MyBlockingQueue<Integer> queue=new MyBlockingQueue<>(100);
for(int i=0;i<5;i++){
new Thread(()->{
while (true){
synchronized (queue){
try {
queue.put(1);
System.out.println("面包+1,库存:"+queue.getSize());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
//消费者,取元素
for(int i=0;i<20;i++){
new Thread(()->{
while(true){
synchronized (queue){
try {
Integer t=queue.take();
System.out.println("面包-1,库存:"+queue.getSize());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
二,java.util.concurrent包下提供主要的几种阻塞队列
ArrayBlockingQueue:基于数组实现的一个阻塞队列,在创建ArrayBlockingQueue对象时必须制定容量大小。并且可以指定公平性与非公平性,默认情况下为非公平的,即不保证等待时间最长的队列最优先能够访问队列。
LinkedBlockingQueue:基于链表实现的一个阻塞队列,在创建LinkedBlockingQueue对象时如果不指定容量大小,则默认大小为Integer.MAX_VALUE。
PriorityBlockingQueue:以上2种队列都是先进先出队列,而PriorityBlockingQueue会按照元素的优先级对元素进行排序,按照优先级顺序出队,每次出队的元素都是优先级最高的元素。注意,此阻塞队列为无界阻塞队列,即容量没有上限。
DelayQueue:基于PriorityQueue,一种延时阻塞队列,DelayQueue中的元素只有当其指定的延迟时间到了,才能够从队列中获取到该元素。DelayQueue也是一个无界队列,因此往队列中插入数据的操作(生产者)永远不会被阻塞,而只有获取数据的操作(消费者)才会被阻塞。
常用方法:
put(E e) 向队尾存入元素,如果队列满,则等待;
take() 从队首取元素,如果队列为空,则等待;
offer(E e,long timeout, TimeUnit unit) 向队尾存入元素,如果队列满,则等待一定的时间,当时 间期限达到时,如果还没有插入成功,则返回false;否则返回true;
poll(long timeout, TimeUnit unit) 从队首取元素,如果队列空,则等待一定的时间,当时间期限 达到时,如果未取到,则返回null;否则返回取得的元素;