0

0

Java中的SynchronousQueue如何做到零容量传递_put与take必须交替执行的握手机制

P粉602998670

P粉602998670

发布时间:2026-03-12 06:59:16

|

256人浏览过

|

来源于php中文网

原创

synchronousqueue 的 put() 会一直阻塞,直到有线程调用 take(),因为它不存储元素,put() 实际是挂起当前线程等待配对的 take() 线程完成 handoff。

java中的synchronousqueue如何做到零容量传递_put与take必须交替执行的握手机制

为什么 SynchronousQueueput() 会一直阻塞,直到有线程调用 take()

SynchronousQueue 不是“队列”,它根本没地方存元素。所谓“入队”其实是把线程挂起,等另一个线程来“取”,双方直接 handoff(交接)。这决定了它的核心行为:没有配对操作,put() 就卡住,take() 也卡住。

常见错误现象:put("x") 后程序停住不动,日志断在这一行,CPU 占用低 —— 不是死锁,是正常等待配对;如果只启动生产者没启消费者,它永远等下去。

  • 它不缓存任何元素,容量恒为 0,size() 永远返回 0isEmpty() 永远返回 true
  • 不支持 peek()iterator()toArray() 等查看类操作,调用会抛 UnsupportedOperationException
  • 所有阻塞都基于线程协作:一个线程进 put(),必须有另一个线程在同一时刻进 take(),才能完成数据传递

offer()poll()SynchronousQueue 中为何几乎总返回 false

offer(E e)poll() 是非阻塞的“试探性”操作。在 SynchronousQueue 中,它们只在“对方线程恰好正在等待”时才成功 —— 这种时机极难捕捉,实际使用中基本等于“运气好才成”。

使用场景有限:仅适合做快速探测(比如判断当前是否有消费者就绪),不能用于可靠投递或消费。

立即学习Java免费学习笔记(深入)”;

Unscreen
Unscreen

AI智能视频背景移除工具

下载
  • offer("x") 成功的前提:此刻已有线程阻塞在 take() 上;否则立刻返回 false
  • poll() 成功的前提:此刻已有线程阻塞在 put("y") 上;否则立刻返回 null
  • 带超时的 offer(e, timeout, unit)poll(timeout, unit) 更实用些,但本质仍是“等一个配对线程出现”,不是“等数据准备好”

LinkedTransferQueue 混用时,为什么握手机制突然失效

看起来都是“传输队列”,但 LinkedTransferQueue 有真实存储能力(内部是链表),transfer() 才模拟握手;而 SynchronousQueue 的握手是强制、无条件的。混用会导致语义错位。

典型坑:把 SynchronousQueue 当作轻量版缓冲队列用,发现吞吐上不去、线程大量阻塞,换成 LinkedTransferQueue 后看似“不卡了”,实则掩盖了生产/消费速率不匹配的问题。

  • SynchronousQueue 强制要求生产者和消费者节奏严格对齐;LinkedTransferQueue 允许暂存,transfer() 成功后仍可继续 put()
  • 两者构造参数不同:SynchronousQueue 不接受容量参数;LinkedTransferQueue 构造函数无参,也不设限
  • 性能差异明显:SynchronousQueue 握手开销小,但依赖线程调度精度;LinkedTransferQueue 多一次节点分配和链表操作,但容错性强

调试时怎么确认是不是被 SynchronousQueue 卡住了

看线程堆栈最直接。JDK 自带工具或 IDE 的线程视图里,如果看到大量线程停在 SynchronousQueue.transfer()AbstractQueuedSynchronizer$ConditionObject.await(),基本就是它。

关键线索是线程状态:WAITING(不是 BLOCKED)且堆栈含 SynchronousQueue 相关方法。

  • jstack <pid></pid> 抓堆栈,搜索 "SynchronousQueue""transfer"
  • 注意区分:如果是 take() 卡住,堆栈通常含 TransferStack.awaitFulfill()put() 卡住则多见 TransferStack.transfer()
  • 不要只看队列是否为空——size() 永远是 0,这个值毫无诊断价值

真正难的是配对时机稍纵即逝,比如消费者启动慢了几十毫秒,生产者就卡住;这种竞态不会报错,只会让系统响应变慢或假死。得盯住线程生命周期和启动顺序。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

254

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

1089

2024.03.01

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

443

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

605

2023.08.10

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

443

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

605

2023.08.10

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

765

2023.08.10

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

9

2026.03.11

Go高并发任务调度与Goroutine池化实践
Go高并发任务调度与Goroutine池化实践

本专题围绕 Go 语言在高并发任务处理场景中的实践展开,系统讲解 Goroutine 调度模型、Channel 通信机制以及并发控制策略。内容包括任务队列设计、Goroutine 池化管理、资源限制控制以及并发任务的性能优化方法。通过实际案例演示,帮助开发者构建稳定高效的 Go 并发任务处理系统,提高系统在高负载环境下的处理能力与稳定性。

22

2026.03.10

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 4.3万人学习

C# 教程
C# 教程

共94课时 | 11.1万人学习

Java 教程
Java 教程

共578课时 | 80.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号