什么是阻塞队列:
当队列为空时,消费者线程阻塞;当队列满时,生产者线程阻塞
队列回顾:
Queue -- 队列 是接口,其实现类有:LinkedList ....
特点:先进先出
存取元素的方法:
offer(E):boolean 从队尾入队
poll():E 从对首出队元素(元素会从队列中删除)
- 若队列为空,返回null
peek():E 从对首获取元素(元素不会从队列中删除)
- 若队列为空,返回null
Deque -- 双端队列 是接口,extedns Queue
实现类:LinkedList
特点:两端均可以入队和出队
入队出队api方法:
入队: offer系列
- offer(e)
- offerFirst(e)
- offerLast(e)
出队: poll系列
- poll():E 从队首取元素
- pollFist():E
- pollLast():E
获取: peek系列
- peek():E
- peekFirst():E
- peekLast():E
stack -- 栈:
将双端队列的队尾封死,只留队首进行存取元素,此时数据结构成为了栈
特点:先进后出
栈中存取元素的叫法:压栈 弹出
栈中不叫队首,叫栈顶,栈底
方法: push(E) pop():E
为什么要有阻塞队列(优点)
阻塞队列可以实现生产者和消费者的解耦,从而提高二者的执行效率
阻塞队列(优点)例图1:
阻塞队列(优点)例图2:
阻塞队列的使用
丶BlockingQueue - 接口
实现类: LinkedBlockingQueue,通过构造方法可以自定义容量 linked 链表
存取元素方法:(使用带有阻塞效果的方法)
put(E): 存元素,若队列满,则阻塞,等队列有空余,阻塞解除
take():E 出队元素,若队列空,则阻塞,直到有可用值,阻塞解除
生产者消费者并发执行,各自阻塞模拟
1.生产者和消费者并发执行,生产者阻塞
生产者和消费者并发执行,生产者每隔2s产生一个数据存入队列;消费者一直不停的取数据.此时就会出现消费者阻塞的情况
/**
* 生产者和消费者并发执行,消费者阻塞
* 让生产者每隔2s产生数据并存入队列
* 消费者持续的取数据
*/
public class ConsumerBlockDemo {
public static void main(String[] args) {
//创建阻塞队列对象
BlockingQueue<Integer> queue = new LinkedBlockingQueue<>();
//创建生产者线程
Thread productor = new Thread(){
@Override
public void run() {
//每隔2s产生一个数据存入队列
try {
while (true) {
Thread.sleep(2000);
int ran = (int) (Math.random() * 50 + 50);
queue.put(ran);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
//创建消费者线程
Thread consumer = new Thread(){
@Override
public void run() {
//持续的从队列中取数据
while (true){
try {
System.out.println(queue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
productor.start();
consumer.start();
}
}
2.生产者和消费者并发执行,消费者阻塞的模拟
生产者和消费者并发执行,生产者每隔2s产生一个数据存入队列;消费者一直不停的取数据.此时就会出现消费者阻塞的情况
生产者和消费者并发执行,生产者存元素的速度大于消费者取元素的速度
/**
* 生产者和消费者并发执行,消费者阻塞
* 让生产者每隔2s产生数据并存入队列
* 消费者持续的取数据
*/
public class ConsumerBlockDemo {
public static void main(String[] args) {
//创建阻塞队列对象
BlockingQueue<Integer> queue = new LinkedBlockingQueue<>();
//创建生产者线程
Thread productor = new Thread(){
@Override
public void run() {
//每隔2s产生一个数据存入队列
try {
while (true) {
Thread.sleep(2000);
int ran = (int) (Math.random() * 50 + 50);
queue.put(ran);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
//创建消费者线程
Thread consumer = new Thread(){
@Override
public void run() {
//持续的从队列中取数据
while (true){
try {
System.out.println(queue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
productor.start();
consumer.start();
}
}