阻塞队列有哪些?拒绝策略有哪些?

简介: 我是小假 期待与你的下一次相遇 ~


阻塞队列有哪些?

在Java的java.util.concurrent包里面,阻塞队列的实现挺多的,我们可以根据它的功能和结构来记,主要分这么几类:

1. 按容量划分:

  • 有界队列: 就是队列有固定的容量。
  • ArrayBlockingQueue 最经典的一个,底层是数组,创建时必须指定大小。它的生产和消费用同一把锁,性能相对稳定。
  • LinkedBlockingQueue 底层是链表,它既可以是有界的(构造时指定容量),也可以默认是无界的(默认是Integer.MAX_VALUE,几乎相当于无界)。它的生产和消费用了两把锁,在高并发场景下吞吐量通常比ArrayBlockingQueue更高。
  • 无界队列: 理论上是无限的,只要内存够就能一直放。
  • PriorityBlockingQueue 一个支持优先级排序的无界队列。元素必须实现Comparable接口,或者构造时传入Comparator。它出队的顺序是按优先级来的,不是先进先出
  • DelayQueue 一个很特殊的队列,里面放的是实现了Delayed接口的元素。每个元素都有个到期时间,只有到期了的元素才能被取出来。典型应用就是做缓存过期、定时任务调度。

2. 特殊功能的队列:

  • SynchronousQueue 这个队列非常特别,它不存储元素。每一个put操作必须等待一个take操作,就像“手递手”交接一样。它直接传递任务,效率很高,常用于线程池之间直接传递工作。CachedThreadPool用的就是它。
  • LinkedTransferQueueLinkedBlockingQueueSynchronousQueue的结合体。它多了个transfer方法,如果当前有消费者在等待,就直接把元素给消费者;如果没有,就入队,并且会阻塞直到该元素被消费掉。性能很好。

所以,我比较常记的是ArrayBlockingQueueLinkedBlockingQueuePriorityBlockingQueueDelayQueueSynchronousQueue这几个,它们各有各的应用场景。

拒绝策略有哪些?

拒绝策略是线程池的一个组成部分。当线程池的工作队列满了,并且所有线程也都达到最大线程数了,这时候再来新任务,就会触发拒绝策略。Java在ThreadPoolExecutor类里提供了4种内置的策略,都实现了RejectedExecutionHandler接口:

1. AbortPolicy(中止策略 - 默认策略):

  • 做法: 直接抛出一个RejectedExecutionException异常。
  • 感受: “比较粗暴,但好处是能让我们及时感知到系统出了饱和问题。”

2. CallerRunsPolicy(调用者运行策略):

  • 做法: 不抛弃任务,也不抛异常,而是将任务回退给调用者(提交任务的线程),让调用者自己去执行这个任务。
  • 感受: “这是一种‘负反馈’机制。提交任务的线程突然要自己去干活,它就忙起来了,自然就慢下来提交新任务了,给了线程池一个喘息的机会。这个策略在生产环境挺实用的,能平滑地降低流量。”

3. DiscardPolicy(丢弃策略):

  • 做法: 默默地把新提交的任务丢弃掉,不执行,也不给任何通知。
  • 感受: “风险比较大,因为任务丢了我们都不知道。除非是一些无关紧要的场景,否则一般不推荐。”

4. DiscardOldestPolicy(丢弃最老策略):

  • 做法:工作队列里排队时间最长的那个任务(队头的任务)丢掉,然后尝试把新任务再放进队列。
  • 感受: 这个策略有点‘喜新厌旧’。它可能丢弃掉一个非常重要的老任务,风险也挺高的,用的时候得想清楚业务上能不能接受。

当然,如果这四种都不满足需求,我们还可以自己实现RejectedExecutionHandler接口,来自定义拒绝策略,比如把拒绝的任务持久化到磁盘,或者记录日志后发个告警等等。

面试回答

Java中的阻塞队列主要有像ArrayBlockingQueue这种基于数组的有界队列,也有LinkedBlockingQueue这种基于链表可以无界的队列。还有一些特殊用途的,比如按优先级出队的PriorityBlockingQueue,做延时任务的DelayQueue,以及不存元素专门做传递的SynchronousQueue

 

关于拒绝策略,是线程池满载后的处理方式。默认的AbortPolicy会直接抛异常;CallerRunsPolicy会让提交任务的线程自己去执行,这个我们项目在用,能平滑流量;还有两种是直接丢弃任务或者丢弃队列中最老的任务。如果都不行,我们也可以根据业务自己实现一个。


相关文章
|
3月前
|
人工智能 运维 安全
SOC 2.0 来了:不是加人加班,而是加“智能”!——智能化安全运营中心的建设之道
SOC 2.0 来了:不是加人加班,而是加“智能”!——智能化安全运营中心的建设之道
295 15
|
3月前
|
弹性计算 搜索推荐 应用服务中间件
今非昔比:看完阿里云服务器租赁价格,沉默了~
阿里云服务器优惠汇总:轻量应用服务器200M带宽38元起/年,ECS云服务器2核2G仅99元/年,4核16G 89元/月,8核32G 160元/月,香港轻量服务器25元/月起,爆款低至1折,新老用户同享,续费同价,限时抢购!
928 14
|
3月前
|
机器学习/深度学习 人工智能 运维
别只盯着 CPU 爆了!一篇文章带你看懂:从指标到根因的 AIOps 自动化故障定位流水线
别只盯着 CPU 爆了!一篇文章带你看懂:从指标到根因的 AIOps 自动化故障定位流水线
475 15
|
3月前
|
人工智能 BI 开发工具
适合个人开发者的5款开发工具,开发者必须知道
2025年,个人开发者迎来工具黄金时代。本文精选5款高效开发利器:GitHub Copilot(AI智能编程)、Trae(中文友好)、Cursor(项目级理解)、VS Code(开源全能)和Zoho Creator(低代码平台),覆盖从代码生成到应用搭建,助你提升效率,快速实现创意。
1113 2
|
4月前
|
XML 机器学习/深度学习 监控
高级检索增强生成系统:LongRAG、Self-RAG 和 GraphRAG 的实现与选择
检索增强生成(RAG)已超越简单向量匹配,迈向LongRAG、Self-RAG与GraphRAG等高级形态。LongRAG通过大块重叠分片保留长上下文,提升连贯性;Self-RAG引入反思机制,动态判断检索必要性与内容相关性,增强可信度;GraphRAG构建知识图谱,支持多跳推理与复杂关系挖掘。三者分别应对上下文断裂、检索盲目性与关系表达缺失难题,代表2025年RAG工程化核心进展,可依场景组合使用以平衡准确性、成本与复杂度。
423 57
高级检索增强生成系统:LongRAG、Self-RAG 和 GraphRAG 的实现与选择
|
3月前
|
算法 编译器 AI芯片
JAX 训练加速指南:8 个让 TPU 满跑的工程实战习惯
本文总结8条JAX在TPU上高效训练的工程实践:固定Shape、使用bfloat16+FP32主权重、显式pjit切分、jit/vmap/scan融合、优化数据管道、PRNG与Step/Device绑定、Remat与梯度累积、善用Profiler。遵循这些原则可避免重编译与内存瓶颈,最大化TPU算力利用率,实现高效稳定训练。
178 3
JAX 训练加速指南:8 个让 TPU 满跑的工程实战习惯
|
3月前
|
人工智能 运维 Serverless
ModelScope 模型一键上线?FunModel 让你 5 分钟从零到生产
阿里云FunModel推出模型集成新范式,无缝对接ModelScope,支持0代码一键部署热门AI模型,5分钟完成上线。依托Serverless+GPU,实现弹性扩缩容,大幅降低部署门槛与运维成本,让企业高效拥抱AI时代。
|
3月前
|
数据管理 编译器 C++
为什么好多人电脑都是一样的报错。为什么好多游戏和应用安装报错都一样?
简介: 0xc000007b报错常见于游戏和软件启动失败,主要因缺失或版本不符的Visual C++ 运行库所致。多数程序依赖该运行库提供的基础功能,如数学运算、内存管理、文件读写等。若系统中缺少对应版本(如2015、2022),或32/64位不匹配,均会导致报错。解决方法包括安装完整VC运行库、修复损坏DLL文件。建议用户安装VC运行库合集,确保兼容性。
200 5
|
3月前
|
数据采集 数据可视化 数据挖掘
从CSV到交互式地图:用Plotly Express可视化地理数据
交互式地图让数据“活”起来:通过悬停、点击、缩放直观探索地理信息。结合Python的Pandas与Plotly Express,仅需几行代码即可实现散点图、热力图、线路图等可视化,支持自定义样式、动态筛选与多图层叠加,广泛应用于商业分析、环境监测、物流追踪等领域,零基础也能快速上手的空间数据分析利器。
200 1
|
3月前
|
人工智能 算法 架构师
你的团队是"精锐特种兵",还是"草台班子"?就差这一份"源代码"
针对技术团队管理混乱、过度依赖个人的痛点,提出用AI指令将经验转化为标准SOP的解决方案。通过工程化思维重构管理流程,实现团队经验的"开源"与"复用",释放核心人才价值。
324 10

热门文章

最新文章