面试官: 阻塞队列有了解过吗❓说说看

简介: 面试官: 阻塞队列有了解过吗❓说说看

前言

目前正在出一个Java多线程专题长期系列教程,从入门到进阶含源码解读, 篇幅会较多, 喜欢的话,给个关注❤️ ~


承接上节的问题,在上节源码探索中,我们遇到了阻塞队列概念, 本节就一起探讨一下什么是阻塞队列,一起来看下吧~


什么是阻塞队列

在讲之前,我们先说一下为什么要引入阻塞队列。我们知道服务器的资源是有限的,就拿典型的生产者和消费者模型来讲


消费者如果没有东西可以消费了,但是它还是在一直执行,这无疑是在浪费系统资源,所以我们需要阻塞消费者,换过来同理


生产者没有东西可生产了或者说没有地方存储它生产的东西,这时候我们就需要阻塞生产者。


然而,在开发中,这种模型往往运行在多线程环境中,需要对资源共享从而达到更高的性能,但这样也会造成线程安全问题,比如死锁、重复消费所以阻塞队列就是帮我们解决这些问题的


BlockingQueue

下面我们就一起看一下Java中给我们提供了哪些好用的工具,先给大家介绍一下BlockingQueue, 本节我们主要讲它的用法。


BlockingQueue是Java util.concurrent包下的类,BlockingQueue提供了线程安全的队列访问方式,并发包下很多高级同步类的实现都是基于BlockingQueue实现的。


BlockingQueue一般用于生产者-消费者模式,生产者是往队列里添加元素的线程,消费者是从队列里拿元素的线程。BlockingQueue就是存放元素的容器

public interface BlockingQueue<E> extends Queue<E> {....}
复制代码


它本身是一个接口,我们看下它常用的实现类


ArrayBlockingQueue

一个用数组实现的有界阻塞队列,此队列按照先进先出(FIFO)的原则对元素进行排序, 支持公平锁和非公平锁。


  • add() 添加元素
// 初始化 容量为3
BlockingQueue<String> queue = new ArrayBlockingQueue<>(3);
System.out.println(queue.add("1"));
System.out.println(queue.add("2"));
System.out.println(queue.add("3"));
System.out.println(queue.add("4"));
复制代码


我们发现添加到4的时候,报错了Exception in thread "main" java.lang.IllegalStateException: Queue full


  • remove() 移除元素,如果为空,会返回异常
// 初始化 容量为3
BlockingQueue<String> queue = new ArrayBlockingQueue<>(3);
System.out.println(queue.add("1"));
System.out.println(queue.add("2"));
System.out.println(queue.add("3"));
// System.out.println(queue.add("4"));
System.out.println(queue.remove());
System.out.println(queue);
复制代码


打印:

true
true
true
1
[2, 3]
复制代码


从结果来看,符合FIFO规则,如果我想移除指定元素怎么办呢?很简单,使用remove("3")


  • offer() 和add方法类似,但是它不会报错,它会返回false, offer(e,time,unit)支持超时
BlockingQueue<String> queue = new ArrayBlockingQueue<>(3);
System.out.println(queue.offer("1"));
System.out.println(queue.offer("2"));
System.out.println(queue.offer("3"));
System.out.println(queue.offer("4"));
复制代码


true
true
true
false
复制代码


  • poll() 与remove相似,但它不会返回异常而是返回null, poll(time,unit)
BlockingQueue<String> queue = new ArrayBlockingQueue<>(3);
System.out.println(queue.poll());
复制代码


null
复制代码


  • take() 与 poll类似, 但它会造成线程阻塞
public static void main(String[] args) throws InterruptedException {
    BlockingQueue<String> queue = new ArrayBlockingQueue<>(3);
    System.out.println(queue.take());
}
复制代码


运行后,我们发现程序被阻塞了

  • put() 添加元素,当容器满的时候,会造成线程阻塞
public static void main(String[] args) throws InterruptedException {
        BlockingQueue<String> queue = new ArrayBlockingQueue<>(1);
        queue.put("1");
        queue.put("2");
    }
复制代码


运行后发现,执行到2的时候被阻塞了

以上是它的常用方法,其它的实现类就不一一给大家演示了,方法差不多,都是基于BlockingQueue接口,可以自己试着运行一下看看


LinkedBlockingQueue

一个由链表结构组成的有界队列,此队列的长度为Integer.MAX_VALUE


SynchronousQueue

是一个不存储元素的阻塞队列,每一个put操作必须等待take操作,否则不能添加元素。支持公平锁和非公平锁。SynchronousQueue的一个使用场景是在线程池里。

Executors.newCachedThreadPool()就使用了SynchronousQueue,这个上节我们讲线程复用的时候遇到过


LinkedTransferQueue

是一个由链表结构组成的无界阻塞队列,相当于其它队列,LinkedTransferQueue队列多了transfer和tryTransfer方法。


PriorityBlockingQueue

是一个支持线程优先级排序的无界队列,默认自然序进行排序,也可以自定义实现compareTo()方法来指定元素排序规则,不能保证同优先级元素的顺序。


DelayQueue

一个实现PriorityBlockingQueue实现延迟获取的无界队列,在创建元素时,可以指定多久才能从队列中获取当前元素。只有延时期满后才能从队列中获取元素,在缓存设计和定时任务调度中经常会遇到。


结束语

本节主要给大家介绍了常用的阻塞队列以及它的基本使用。下一节, 带大家探索一下ArrayBlockingQueue源码,看下阻塞队列是如何实现的 ~

相关文章
|
8月前
|
安全
阻塞队列的安全实现,定时器的安全实现(面试易考),超详细(一)
阻塞队列的安全实现,定时器的安全实现(面试易考),超详细
|
8月前
|
安全
阻塞队列的安全实现,定时器的安全实现(面试易考),超详细(二)
阻塞队列的安全实现,定时器的安全实现(面试易考),超详细
|
1月前
|
监控 安全 Java
【多线程学习】深入探究阻塞队列与生产者消费者模型和线程池常见面试题
【多线程学习】深入探究阻塞队列与生产者消费者模型和线程池常见面试题
|
1月前
|
安全 Java
【面试问题】Java 中的阻塞队列用过哪些?
【1月更文挑战第27天】【面试问题】Java 中的阻塞队列用过哪些?
|
8月前
|
设计模式 存储 安全
面试易考:多线程模式下的单例模式两种具体实现(饿汉,懒汉),两个的线程安全性,阻塞队列,生产者消费者模型
面试易考:多线程模式下的单例模式两种具体实现(饿汉,懒汉),两个的线程安全性,阻塞队列,生产者消费者模型
|
10月前
|
存储 消息中间件 安全
第二季:7阻塞队列知道吗?【Java面试题】
第二季:7阻塞队列知道吗?【Java面试题】
34 0
|
Java API
2020大厂面试JUC线程重要技术点【集合+线程+阻塞队列+线程池】(下)
2020大厂面试JUC线程重要技术点【集合+线程+阻塞队列+线程池】(下)
112 0
2020大厂面试JUC线程重要技术点【集合+线程+阻塞队列+线程池】(下)
|
安全 Java
2020大厂面试JUC线程重要技术点【集合+线程+阻塞队列+线程池】(上)
2020大厂面试JUC线程重要技术点【集合+线程+阻塞队列+线程池】(上)
96 0
2020大厂面试JUC线程重要技术点【集合+线程+阻塞队列+线程池】(上)
|
存储 消息中间件 Java
详解java中一个面试常问的知识点-阻塞队列
学习数据结构的时候介绍过队列,今天介绍一种队列的其中一种,叫做阻塞队列。这个知识点属于多线程中的一个模块,对于我们理解消息中间件有份非常大的用处,希望对你有帮助。
143 0
详解java中一个面试常问的知识点-阻塞队列