阻塞队列
1.什么是阻塞队列?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p7IzPIyN-1621378757606)(C:\Users\ThinkPad\AppData\Roaming\Typora\typora-user-images\image-20210327011406739.png)]
顾名思义,阻塞队列就是一个队列,如图,线程1向队列中添加元素,而线程2从队列中移除元素;
当队列满时,向队列中添加元素时就会阻塞,直至其他线程从队列中移除元素;当队列空时,从队列中移除元素时就会阻塞,直至其他元素向队列中添加元素;
2.为什么要使用阻塞队列?
在concurrent包发布之前,需要认为的控制线程的阻塞与唤醒;但随着concurrent包的发布,我们使用阻塞队列时,不用再去担心线程的阻塞与唤醒,这一切全部被阻塞队列包办了。
3.阻塞队列的分类
- ArrayBlockingQueue 由数组组成的有界阻塞队列
- LinkedBlockingQueue 由链表组成的有界阻塞队列<但其大小默认值为Integer.MAX_VALUE>
- SyschronousQueue 不存储元素的阻塞队列(零库存),单个元素的阻塞队列,也就是生产 一个消费一个
- PriorityBlockingQueue 支持优先级排序的无界阻塞队列
- DelayQueue 使用优先级队列实现的延时无界阻塞队列
- LinkedTransferQueue 由链表组成的无界阻塞队列
- LinkedBlockingDueue 由链表组成的双向阻塞队列
4.阻塞队列的核心用法
方法类型 | 抛出异常 | 返回布尔 | 阻塞 | 超时 |
---|---|---|---|---|
插入 | add(E e) | offer(E e) | put(E e) | offer(E e,Time,TimeUnit) |
移除 | remove() | poll() | take() | poll(Time,TimeUnit) |
检查 | element() | peek() | 无 | 无 |
4.1抛出异常
- 当阻塞队列满时,再往队列里add插入元素会抛IllegalStateException:Queue full
public static void main(String[] args) {
BlockingQueue<Integer> blockingQueue1 = new ArrayBlockingQueue<>(3);
System.out.println(blockingQueue1.add(1));
System.out.println(blockingQueue1.add(2));
System.out.println(blockingQueue1.add(3));
System.out.println(blockingQueue1.add(4));
// System.out.println(blockingQueue1.element());
// System.out.println(blockingQueue1.remainingCapacity());
// System.out.println(blockingQueue1.remove());
// System.out.println(blockingQueue1.remove());
// System.out.println(blockingQueue1.remove());
// System.out.println(blockingQueue1.element());
// System.out.println(blockingQueue1.remainingCapacity());
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2QMm5sQK-1621378757608)(C:\Users\ThinkPad\AppData\Roaming\Typora\typora-user-images\image-20210327014335639.png)]
- 当阻塞队列空时,再往队列里remove移除元素会抛NoSuchElementException
public static void main(String[] args) {
BlockingQueue<Integer> blockingQueue1 = new ArrayBlockingQueue<>(3);
blockingQueue1.add(1);
blockingQueue1.add(2);
blockingQueue1.add(3);
// System.out.println(blockingQueue1.add(4));
// System.out.println(blockingQueue1.element());
// System.out.println(blockingQueue1.remainingCapacity());
System.out.println(blockingQueue1.remove());
System.out.println(blockingQueue1.remove());
System.out.println(blockingQueue1.remove());
System.out.println(blockingQueue1.element());
// System.out.println(blockingQueue1.remainingCapacity());
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fHdxUVEv-1621378757610)(C:\Users\ThinkPad\AppData\Roaming\Typora\typora-user-images\image-20210327015249383.png)]
4.2返回布尔
-
插入方法,成功 ture 失败 false
-
移除方法,成功返回出队列的元素,队列里面没有就返回null
public static void main(String[] args) {
BlockingQueue<Integer> blockingQueue1 = new ArrayBlockingQueue<>(3);
System.out.println(blockingQueue1.offer(1));
System.out.println(blockingQueue1.offer(2));
System.out.println(blockingQueue1.offer(3));
System.out.println(blockingQueue1.offer(4));
System.out.println(blockingQueue1.peek());
System.out.println(blockingQueue1.poll());
System.out.println(blockingQueue1.poll());
System.out.println(blockingQueue1.poll());
System.out.println(blockingQueue1.poll());
System.out.println(blockingQueue1.peek());
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1fdygttD-1621378757611)(C:\Users\ThinkPad\AppData\Roaming\Typora\typora-user-images\image-20210327020108538.png)]
4.3一直阻塞
-
当阻塞队列满时,生产者线程继续往队列里put元素,队列会一直阻塞生产线程直到put数据成功或者响应中断退出。
-
当阻塞队列空时,消费者线程试图从队列里take元素,队列会一直阻塞消费者线程直到队列可用。
public static void main(String[] args) throws InterruptedException { BlockingQueue<Integer> blockingQueue1 = new ArrayBlockingQueue<>(3); blockingQueue1.put(1); blockingQueue1.put(2); blockingQueue1.put(3); System.out.println(blockingQueue1.take()); System.out.println(blockingQueue1.take()); System.out.println(blockingQueue1.take()); System.out.println(blockingQueue1.take()); }
4.4超时退出
当阻塞队列满时,队列会阻塞生产者线程一定时间,超过后限时后生产者线程会退出
public static void main(String[] args) throws InterruptedException{
BlockingQueue<Integer> blockingQueue1 = new ArrayBlockingQueue<>(3);
System.out.println(blockingQueue1.offer(1, 2, TimeUnit.SECONDS));
System.out.println(blockingQueue1.offer(1, 2, TimeUnit.SECONDS));
System.out.println(blockingQueue1.offer(1, 2, TimeUnit.SECONDS));
System.out.println(blockingQueue1.offer(1, 2, TimeUnit.SECONDS));
}
4.5SyschronousQueue
public static void main(String[] args) throws InterruptedException{
BlockingQueue blockingQueue = new SynchronousQueue();
new Thread(()->{
try {
blockingQueue.put(1);
blockingQueue.put(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
},"AAA").start();
new Thread(()->{
try {
Thread.sleep(3000);
System.out.println(blockingQueue.take());
Thread.sleep(3000);
System.out.println(blockingQueue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
},"BBB").start();
}