Java高频面试题:什么是阻塞队列?

1.什么是阻塞线程?

阻塞队列和普通的队列的区别是:

当阻塞队列是空的,从队列中获取元素的操作将会被阻塞;

当阻塞队列是满的,往队列里添加元素的操作将会被阻塞;

试图从空的阻塞队列中获取元素的线程将会被阻塞,直到其他的线程往空的队列插入新的元素;

同样,试图从满的阻塞队列中添加新元素的线程同样也会被阻塞,直到其他线程从列中移除一个或者多个元素或者完全清空队列使队列重新变得空闲起来并后续新增。

在多线程领域里:所谓阻塞,在某些情况下会挂起线程,一旦条件满足,被挂起的线程又会自动被唤醒。

2.为什么需要BlockingQueue?

好处是我们不需要关心什么时候需要阻塞线程,什么时候需要唤起线程,因为这一切BlockingQueue都给你一手包办了。

在concurrent包发布以前,在多线程环境下,我们每个程序员必须去自己控制这些细节,尤其还要兼顾效率和线程安全,而这会给我们的程序带来不小的复杂度。

3.有哪些常见的阻塞队列?(加粗的是常用的)

  • ArrayBlockingQueue:由数组结构组成的有界阻塞队列
  • LinkedBlockingQueue:由链表结构组成的有界(但大小默认值为Integer.MAX_VALUE)阻塞队列
  • PriorityBlockingQueue:支持优先级排序的无界阻塞队列
  • DelayBlockingQueue:使用优先级队列实现的延迟无界阻塞队列
  • SynchronousQueue:不存储元素的阻塞队列,也即单个元素的队列,只存一个元素
  • LinkedTransferQueue:由链表结构组成的无界阻塞队列
  • LinkedBlockingDeque:由链表结构组成的双向阻塞队列

SynchronousQueue没有容量。与其他BlockingQueue不同,SynchronousQueue是不存储元素,每一个put操作必须要等待一个take操作,否则不能继续添加元素,反之亦然。

4.BlockingQueue的核心方法

BlockingQueue的核心方法:

插入 add(e) offer(e) put(e) offer(e,time,unit)

移除 remove() poll() take() poll(time,unit)

检查 element() peek()

  • 当阻塞队列满的时候,再往队列里add插入元素会抛出IllegalStateException: Queue full异常;
  • 当阻塞队列空的时候,再往队列里remove移除元素,会抛出NoSuchElementException异常;
  • 使用offer(e)添加元素,不抛异常,成功返回true,失败返回false;
  • 使用poll()移除元素时,不抛异常,成功返回队列里的元素值,失败返回null;
  • 当阻塞队列满的时候,生产者线程继续使用put(e)插入元素,会一直阻塞直到put成功,或者响应中断退出;
  • 当阻塞队列空的时候,消费者线程试图从队列里take元素,队列会一直阻塞,直到消费者线程可用;
  • 当阻塞队列满时,会等待一段时间,超时后退出:offer(e,time,unit)和poll(time,unit)。

演示示例:

(1)ArrayBlockingQueue添加元素示例:创建了一个大小为3的阻塞队列,当存入第四个元素的时候,抛出IllegalStateException: Queue full异常。
public class BlockingQueueDemo {
    public static void main(String[] args) {
        BlockingQueue blockingQueue = new ArrayBlockingQueue(3);
        System.out.println(blockingQueue.add('a'));
        System.out.println(blockingQueue.add('b'));
        System.out.println(blockingQueue.add('c'));
        System.out.println(blockingQueue.add('d'));
    }
}
报错:Exception in thread "main" java.lang.IllegalStateException: Queue full
(2)ArrayBlockingQueue移除元素示例:当阻塞队列为空时,移出元素抛出NoSuchElementException异常
public class BlockingQueueDemo {
    public static void main(String[] args) {
        BlockingQueue blockingQueue = new ArrayBlockingQueue(3);
        System.out.println(blockingQueue.add('a'));
        System.out.println(blockingQueue.add('b'));
        System.out.println(blockingQueue.add('c'));
//        System.out.println(blockingQueue.add('d'));
        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());
    }
}

报错:NoSuchElementException

全部评论
可以
点赞 回复 分享
发布于 2021-03-20 16:14
感谢参与【创作者计划2期·技术干货场】!欢迎更多牛油来写干货,瓜分总计20000元奖励!!技术干货场活动链接:https://www.nowcoder.com/link/czz2jsghtlq(参与奖马克杯将于每周五结算,敬请期待~)
点赞 回复 分享
发布于 2021-03-15 20:35

相关推荐

迷茫的大四🐶:都让开,我tm来啦
点赞 评论 收藏
分享
最近群里有很多同学找我看简历,问问题,主要就是集中在明年三月份的暑期,我暑期还能进大厂嘛?我接下来该怎么做?对于我来说,我对于双非找实习的一个暴论就是title永远大于业务,你在大厂随随便便做点慢SQL治理加个索引,可能就能影响几千人,在小厂你从零到一搭建的系统可能只有几十个人在使用,量级是不一样的。对双非来说,最难的就是约面,怎么才能被大厂约面试?首先这需要一点运气,另外你也需要好的实习带给你的背书。有很多双非的同学在一些外包小厂待了四五个月,这样的产出有什么用呢?工厂的可视化大屏业务很广泛?产出无疑是重要的,但是得当你的实习公司到了一定的档次之后,比如你想走后端,那么中厂后端和大厂测开的选择,你可以选择中厂后端(注意,这里的中厂也得是一些人都知道的,比如哈啰,得物,b站之类,不是说人数超过500就叫中厂),只有这个时候你再去好好关注你的产出,要不就无脑大厂就完了。很多双非同学的误区就在这里,找到一份实习之后,就认为自己达到了阶段性的任务,根本不再投递简历,也不再提升自己,玩了几个月之后,美其名曰沉淀产出,真正的好产出能有多少呢?而实际上双非同学的第一份实习大部分都是工厂外包和政府外包!根本无产出可写😡😡😡!到了最后才发现晚了,所以对双非同学来说,不要放过任何一个从小到中,从中到大的机会,你得先有好的平台与title之后再考虑你的产出!因为那样你才将将能过了HR初筛!我认识一个双非同学,从浪潮到海康,每一段都呆不久,因为他在不断的投递和提升自己,最后去了美团,这才是双非应该做的,而我相信大部分的双非同学,在找到浪潮的那一刻就再也不会看八股,写算法,也不会打开ssob了,这才是你跟别人的差距。
迷茫的大四🐶:我也这样认为,title永远第一,只有名气大,才有人愿意了解你的简历
双非本科求职如何逆袭
点赞 评论 收藏
分享
评论
5
13
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务