文章目录:
一、阻塞队列
1. 阻塞队列简介
阻塞队列是基于普通队列做出的扩展,依旧符合“先进先出”的原则。
阻塞队列具有以下特性:
-
如果针对一个已经满了的队列进行入队,此时入队操作就会阻塞,一直阻塞到队列不满(其他线程出队元素)之后
-
如果针对一个已经空了的队列进行出队,此时出队操作就会阻塞,一直阻塞到队列不空(其他线程入队元素)之后
基于以上特性,阻塞队列是一种线程安全的数据结构
2. Java标准库提供的阻塞队列
包:java.util.concurrent
接口:BlockingQueue
集合: ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue
方法:
put:带有阻塞功能的入队列
take:带有阻塞功能的出队列
以及不带有阻塞功能的offer、poll、peek方法,但是并没有提供获取队首元素的方法
简单使用:
//Java标准库的阻塞队列
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class ThreadDemo10 {
public static void main(String[] args) throws InterruptedException {
BlockingQueue<String> queue = new ArrayBlockingQueue<>(100);
queue.put("aaa");
String elem = queue.take();
System.out.println("elem = " + elem);
elem = queue.take();
System.out.println("elem = " + elem);
}
}
运行结果:
这里只能输出一个“aaa”,是因为原本队列中只入队列了一个元素,在第一次出队后,队列为空,再次出队就会发生阻塞,直至队列有新的元素添加进去供其出队。
二、实现阻塞队列
1. 先实现一个普通队列
使用循环队列,用字符串数组elems来存储元素,不考虑泛型,存储元素类型为String
并实现最基本的入队和出队
//实现阻塞队列,不考虑泛型 存储类型为String
public class MyBlockingQueue {
private String[] elems = null;
private int head = 0;
private int tail = 0;
private int size = 0;
public MyBlockingQueue(int capacity){
elems = new String[capacity];
}
public void put(String elem){
if(size >= elems.length){
//队列满 需要阻塞
return;
}
elems[tail] = elem;
tail++;
//写法一 好理解 + 高效 小胜一筹
//条件跳转指令 高效
//很少触发赋值操作
if(tail >= elem.length()){
tail = 0;
}
//