目录
- ArrayDeque的特点
- BlockingQueue
- 什么是BlockingQueue?
- 什么叫阻塞队列?
- 阻塞队列的应用场景是什么?
- BlockingQueue的阻塞方法是什么?
- BlockingQueue的四类方法
- code
- code2
ArrayDeque的特点
- ArrayDeque是Deque接口子实现
- ArrayDeque数据结构可以表示为: 队列、双端队列、栈
- ArrayDeque是一个循环数组
- ArrayDeque底层数组的默认初始长度16,默认扩容机制扩为原来的2倍
- ArrayDeque存储数据有序
- ArrayDeque允许存储重复数据
- ArrayDeque不允许存储null
- ArrayDeque线程不安全
- 如果我们在使用ArrayDeque的时候,在其构造方法中传入指定的数组长度,它会对这个给定长度进行处理。默认底层数组长度是8,如果给的值大于等于8那么会产生一个大于这个给定值的最小的2的幂值作为最终的底层数组长度
给定10 -> 数组实际长度是16
给定20 -> 数组实际长度是32
给定40 -> 数组实际长度是64
给定64 -> 数组实际长度是128
即ArrayDeque的底层数组长度永远保持2的幂值
//底层源码
// 假设给定20
private static int calculateSize(int numElements) {
// int MIN_INITIAL_CAPACITY = 8;
int initialCapacity = MIN_INITIAL_CAPACITY;
// 20 >= 8
if (numElements >= initialCapacity) {
// initialCapacity = 20
initialCapacity = numElements;
// initialCapacity = 20
// 10100
// 第一步:
// >>> 1 01010
// 10100
// | 11110
initialCapacity |= (initialCapacity >>> 1);
// 第二步:
// >>> 2 00111
// 11110
// | 11111
initialCapacity |= (initialCapacity >>> 2);
// 第三步:
// >>> 4 00001
// 11111
// | 11111
initialCapacity |= (initialCapacity >>> 4);
initialCapacity |= (initialCapacity >>> 8);
initialCapacity |= (initialCapacity >>> 16);
// 11111
// ++
// 100000
initialCapacity++;
if (initialCapacity < 0) // Too many elements, must back off
initialCapacity >>>= 1;// Good luck allocating 2 ^ 30 elements
}
return initialCapacity;
}
BlockingQueue
什么是BlockingQueue?
BlockingQueue是阻塞队列
什么叫阻塞队列?
是一个大小容量有限的队列
- 在添加数据的时候,如果队列满了,那么添加线程等待(直到有一个线程删除了队列中的元素,添加线程才可以往里面添加元素)
- 在删除数据的时候,如果队列空了,那么删除线程等待(直到有一个线程往队列中添加了元素,删除线程才可以进行删除操作)
阻塞队列的应用场景是什么?
- 缓存
- 生产者-消费者模型
BlockingQueue的阻塞方法是什么?
普通的阻塞方法:(不满足条件, 一直阻塞)
- put() —— 在添加数据的时候,,如果队列满了,put操作等待
- take() —— 在删除数据的时候,如果队列空了,take操作等待
超时阻塞(不满足条件,会等待一段时间,在这个设置的时间内没有等到结果,返回特殊值null或false)
- offer(e, time, unit) —— 没插入成功,返回false
- poll( time, unit) —— 没取出元素,返回null
BlockingQueue的四类方法
code
package cs.kaoyan.javase.com.queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;
public class Test1 {
public static void main(String[] args) throws InterruptedException {
//阻塞队列容量为2
ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<String>(2);
//先向队列中添加两个元素
queue.add("zhang san");
queue.add("li si");
//add方法:报错IllegalStateException: Queue full
//queue.add("wang wu");
//put方法:阻塞
//队列已满
//queue.put("wang wu");
//十秒之后还没添加成功会返回true
//boolean result = queue.offer("wang wu", 10, TimeUnit.SECONDS);
//false
//System.out.println(result);
ArrayBlockingQueue<String> queue2 = new ArrayBlockingQueue<>(2);
//队列为空,无元素可取,返回null
//String poll = queue2.poll();
//System.out.println(poll);
//队列为空,无元素可取,阻塞
queue2.take();
}
}
code2
package cs.kaoyan.javase.com.queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;
public class Test2 {
public static void main(String[] args) throws InterruptedException {
//容量为2的阻塞队列
ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<String>(2);
//先向队列中插入两个元素
queue.offer("zhang san");
queue.offer("li si");
MyThread myThread = new MyThread(queue);
//启动子线程
myThread.start();
//队列已满,无法加入wang wu
//如果7秒后依旧不能插入元素,返回false
queue.offer("wang wu",7, TimeUnit.SECONDS);
//子线程休眠五秒之后,会移除zhang san,再过两秒,可以将wang wu插入队列
//[li si, wang wu]
System.out.println(queue);
}
}
class MyThread extends Thread{
//成员变量
ArrayBlockingQueue<String> queue;
//构造器
public MyThread(ArrayBlockingQueue<String> queue) {
this.queue = queue;
}
@Override
public void run(){
//重写run方法
//子线程休眠五秒
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
queue.poll();
}
}