3年java开发竟然还不知道Lambda的这个坑

简介: 3年java开发竟然还不知道Lambda的这个坑

背景

有朋友反馈zk连接很慢。整理出zk连接的关键逻辑如下:
image

上面的代码造成第一次调用ClientZkAgent.getInstance的时候,需耗时10s, 这个时间恰好跟semaphore的超时时间相当. 在此期间,整个世界好像停滞了一样。

分析

在本地重现后,通过jstack获得系统停滞期间的线程栈,发现这个时候zookeeper的EventThread有个比较奇怪的现象:
image

客户端实际上很快就连上了zookeeper并返回后生成了SyncConnected事件,而且EventThread已经在回调Watcher.process方法了,但似乎事件线程就一直hold在上面#_1的位置无法往下走, 同时,lambda表达式变成了ClientZkAgent的一个方法了:lambda$connect$0。
了解了一下Java中lambda的实现方式,事情水落石出了。
image

简而言之,jvm会把lambda表达式转换成所在类的一个方法lambda${method}${seq}(method为该lambda所在的方法名,例如上面的connect方法),同时通过动态代理生成一个代理类(该代理类实现了lambda表达式所代表的具体接口),在该代理类中调用lambda${method}${seq}。
在上面的例子中,生成的代理类大概如下:
image

再梳理一下:
业务线程:
1.通过静态方法ClientZkAgent.getInstance()获取实例,第一次访问的时候会触发类ClientZkAgent的装载。
2.装载过程中,装载静态成员instance,这时候会尝试创建一个ClientZkAgent对象。
3.在ClientZkAgent的构造函数中连接zk,并通过CountdownLatch进入阻塞状态。注意这时候类装载还没完成。
4.CountdownLatch超时后完成对象的初始化以及整个类的加载
zk事件线程:
SyncConnected事件触发后,调用ClientZkAgent.lambda$connect$0(event), 试图唤醒业务线程(唤醒逻辑在lambda中)。
然而这时候ClientZkAgent还没加载完,事件线程只能等待类加载流程的结束。
业务线程加载完ClientZkAgent后,事件线程完成事件的处理。
可见,在这个过程中,两个线程相互等待(类似死锁但不是死锁),直至业务线程超时后才化解这个局面。
欢迎大家关注我的公种浩【程序员追风】,文章都会在里面更新,整理的资料也会放在里面。

解决

修改ClientZkAgent的初始化逻辑如下:
image

最后
欢迎大家一起交流,喜欢文章记得点个赞,感谢支持!

相关文章
|
3月前
|
安全 前端开发 Java
《深入理解Spring》:现代Java开发的核心框架
Spring自2003年诞生以来,已成为Java企业级开发的基石,凭借IoC、AOP、声明式编程等核心特性,极大简化了开发复杂度。本系列将深入解析Spring框架核心原理及Spring Boot、Cloud、Security等生态组件,助力开发者构建高效、可扩展的应用体系。(238字)
|
4月前
|
消息中间件 人工智能 Java
抖音微信爆款小游戏大全:免费休闲/竞技/益智/PHP+Java全筏开源开发
本文基于2025年最新行业数据,深入解析抖音/微信爆款小游戏的开发逻辑,重点讲解PHP+Java双引擎架构实战,涵盖技术选型、架构设计、性能优化与开源生态,提供完整开源工具链,助力开发者从理论到落地打造高留存、高并发的小游戏产品。
|
4月前
|
存储 Java 关系型数据库
Java 项目实战基于面向对象思想的汽车租赁系统开发实例 汽车租赁系统 Java 面向对象项目实战
本文介绍基于Java面向对象编程的汽车租赁系统技术方案与应用实例,涵盖系统功能需求分析、类设计、数据库设计及具体代码实现,帮助开发者掌握Java在实际项目中的应用。
213 0
|
5月前
|
安全 Java API
Java中的Lambda表达式:简洁与功能的结合
Java中的Lambda表达式:简洁与功能的结合
490 211
|
5月前
|
安全 Java 数据库
Java 项目实战病人挂号系统网站设计开发步骤及核心功能实现指南
本文介绍了基于Java的病人挂号系统网站的技术方案与应用实例,涵盖SSM与Spring Boot框架选型、数据库设计、功能模块划分及安全机制实现。系统支持患者在线注册、登录、挂号与预约,管理员可进行医院信息与排班管理。通过实际案例展示系统开发流程与核心代码实现,为Java Web医疗项目开发提供参考。
316 2
|
5月前
|
JavaScript 安全 前端开发
Java开发:最新技术驱动的病人挂号系统实操指南与全流程操作技巧汇总
本文介绍基于Spring Boot 3.x、Vue 3等最新技术构建现代化病人挂号系统,涵盖技术选型、核心功能实现与部署方案,助力开发者快速搭建高效、安全的医疗挂号平台。
320 3
|
5月前
|
移动开发 Cloud Native 安全
Java:跨平台之魂,企业级开发的磐石
Java:跨平台之魂,企业级开发的磐石
|
5月前
|
安全 Oracle Java
JAVA高级开发必备·卓伊凡详细JDK、JRE、JVM与Java生态深度解析-形象比喻系统理解-优雅草卓伊凡
JAVA高级开发必备·卓伊凡详细JDK、JRE、JVM与Java生态深度解析-形象比喻系统理解-优雅草卓伊凡
436 0
JAVA高级开发必备·卓伊凡详细JDK、JRE、JVM与Java生态深度解析-形象比喻系统理解-优雅草卓伊凡