大家好,我是你们熟悉的技术探险家小米,今年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岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号"软件求生",获取更多技术干货!