Exchanger 到底能干嘛?99% 的程序员都没用过的 Java API!



大家好,我是你们熟悉的技术探险家小米,今年31岁,一个爱写代码、爱分享、也爱讲故事的程序员大哥哥~

今天要和大家聊一个我社招面试中遇到的"冷门又经典"的Java并发小知识:Exchanger

别走开,不是什么冷冰冰的API文档!咱们讲个故事,从一场"线程之间的神秘交易"说起。

一场线程之间的秘密交易

那是一个阳光明媚的早晨,我照常打开电脑,一边喝着手冲咖啡一边准备面试。一位朋友推荐我去面一家做高并发电商系统的公司,说他们家主打"技术深度",适合我这种喜欢钻牛角尖的"并发爱好者"。

结果面试官一上来就问了一个很少有人碰过的问题:

"你了解 Java 中 Exchanger 的用法吗?你觉得它在什么场景下最适合?"

我愣了一下------Exchanger?我记得那玩意儿是 JDK 1.5 引进的并发工具类,平常项目里真不太常用。幸好,我曾经在做一个图像处理工具时玩过它,于是我微微一笑,开始讲起了我的故事。

Java 并发世界中的神秘工具 Exchanger

我们先来认识一下这位工具小伙伴。

Exchanger 是谁?

Exchanger 是 Java 提供的一个线程之间交换数据的同步点。简单来说,它就像一个"交易所"------两个线程约好,在某一刻来交换彼此手中的数据。

  • Exchanger 只能让两个线程配对交换数据。
  • 它是阻塞的------必须两个线程都到了交换点,才会完成数据交换。
  • 如果只有一个线程调用了 exchange(),它会一直等,直到另一个线程到来,或者超时。

官方定义

  • 构造方法: Exchanger exchanger = new Exchanger<>();
  • 交换方法: T result = exchanger.exchange(myData);

场景:我用 Exchanger 处理图像对比

说回我当时做的那个图像处理工具项目。需求是这样的:

我们有两组图片,一组是"原图",一组是"处理后的图",我们要做图像质量比对,比如计算相似度、像素差异等。

思路很简单:

  • 两个线程分别从两个目录里读取图像。
  • 读取后在同一个点"交汇",拿到彼此的图像数据。
  • 然后再去做对比、生成报告。

当时我们最开始用的是共享队列 + 锁,但后来发现同步太繁琐,有资源竞争、等待问题,性能也不太理想。

直到我发现了 Exchanger!

我把代码简单封装后,大概是这样:

这段代码的关键是 exchanger.exchange(img),两个线程在这一步同步碰面,互换图像,就像打游戏交换装备一样顺畅!

Exchanger 的底层是怎么实现的?

这时候面试官点点头,说:"那你知道 Exchanger 的底层是怎么实现的吗?"

我笑着说,其实 JDK 里对 Exchanger 的实现很有意思,它使用了一种叫做 "槽位匹配"Slot Matching 的机制。

简单理解就是:

  • Exchanger 内部维护一个叫 Slot 的共享变量。
  • 第一个线程到来,把自己的数据放到 Slot 里,然后阻塞等待。
  • 第二个线程到来,看到有数据,就拿走这个数据,把自己的数据放进去。
  • 然后唤醒第一个线程,完成数据交换。

它不依赖锁,而是用 CAS(Compare And Swap) 保证原子性,效率高,性能好。

当然,它内部其实更复杂,还用了 链表队列超时等待 等机制来支持更复杂的场景。

Exchanger 的典型使用场景

接下来,我又分享了几个 Exchanger 的经典使用场景,都是我项目或者学习中见过的。

1、数据校验与同步

两个线程分别处理不同来源的数据,比如日志采集、网络抓包,然后在某个点做比对。Exchanger 就可以在中间点交换数据,做实时对比。

2、双缓冲机制

常见于游戏开发或视频渲染场景,比如一个线程在画布 A 渲染,另一个线程在画布 B 显示,渲染完成后交换画布。用 Exchanger 切换缓存帧非常自然。

3、加密与解密流水线

一个线程负责读取并加密数据,另一个线程负责接收密文并解密,Exchanger 就像流水线中转口,既保证了同步又避免共享变量的麻烦。

Exchanger 与其他并发工具的对比

"那你怎么判断该用 Exchanger 还是其他工具,比如 BlockingQueue?"面试官继续问。

我回答说:

所以总结一句:Exchanger 是一对一数据同步的利器,而不是广播工具。

一些使用 Exchanger 的小坑

讲完正面的,当然也要分享几个使用 Exchanger 的"坑"。

1、只能两个线程使用,不能多个线程乱入。

超过两个线程,后面到的会阻塞或者抛出异常。

2、容易死锁

如果只有一个线程调用了 exchange(),另一个线程永远不到场,它就会卡住。

3、不能无限等待,建议加上超时机制

比如 exchange(data, 5, TimeUnit.SECONDS),防止程序卡死。

最终结局:拿到 offer!

聊完这些,面试官笑了,表示很少有候选人能把 Exchanger 说得这么详细,还能举出实际项目例子。

当天晚上,我收到了 offer ~

结语:冷门 API 也有春天

我知道很多人在刷题时更偏爱热门的 ReentrantLock、ThreadPoolExecutor、Semaphore,但其实像 Exchanger 这种"冷门 API"也是 Java 并发世界中不可忽视的宝藏。

  • 会用工具,是初级程序员;
  • 知道什么时候该用什么工具,是中高级程序员;
  • 懂得底层原理,能优化使用场景,是架构师。

所以,别看 Exchanger 平常用得少,但它在对的地方能发挥出 100% 的威力。

END

如果你也曾在某个项目里用过 Exchanger,欢迎留言聊聊你的故事 。

如果你是第一次听说这个工具,那我希望这篇文章能成为你走入并发世界的一把钥匙 。

喜欢的话,【点赞】、【分享】、【收藏】三连支持一下我写作吧!

我是小米,一个喜欢分享技术的31岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号"软件求生",获取更多技术干货!

相关推荐
碎叶城李白5 分钟前
NIO简单群聊
java·nio
嘻嘻嘻嘻嘻嘻ys11 分钟前
《Vue 3.3响应式革新与TypeScript高效开发实战指南》
前端·后端
暮乘白帝过重山20 分钟前
路由逻辑由 Exchange 和 Binding(绑定) 决定” 的含义
开发语言·后端·中间件·路由流程
xxjiaz24 分钟前
水果成篮--LeetCode
java·算法·leetcode·职场和发展
CHQIUU24 分钟前
告别手动映射:在 Spring Boot 3 中优雅集成 MapStruct
spring boot·后端·状态模式
广西千灵通网络科技有限公司34 分钟前
基于Django的个性化股票交易管理系统
后端·python·django
CodeFox42 分钟前
动态线程池 v1.2.1 版本发布,告警规则重构,bytebuddy 替换 cglib,新增 jmh 基准测试等!
java·后端
tonydf1 小时前
0帧起手本地跑一下BitNet
后端·ai编程
ℳ₯㎕ddzོꦿ࿐1 小时前
Java集成Zxing和OpenCV实现二维码生成与识别工具类
java·opencv
zzmgc41 小时前
常用JVM配置参数
后端