季度技术评审上被问:JDK 23 要不要跟 8 月底的季度技术评审,架构师抛了个问题:JDK 22 已经用了小半年,JDK 23 再过半个月就 GA,咱们是继续滚动跟版本,还是钉在 JDK 21 LTS 上不动。 当时线上三个集群:订单跑 JDK 17,网关和用户中心跑 JDK 21,还有个新做的
做聚合服务时,要并发调三个下游再合并结果。最早我用 ExecutorService + Future,取消一个、异常处理、超时控制写得一团乱,线程泄漏还出了两次线上问题。JDK 23 的结构化并发(第五次预览,JEP 480)把这套"多任务协同"重新规范了一遍,值得认真看。 旧写法的乱 经典 Fut
JDK 21 预览、JDK 22 二次预览的"字符串模板"(String Templates,JEP 430 / JEP 459),原本被寄望取代丑陋的 String.format 和拼接。结果后来被正式撤回。作为一个写了七年后端的人,我反而觉得这次"撤回"是语言演进里难得的清醒。 它想解决什么 传
去年用 JDK 21 虚拟线程接重构一个 HTTP 聚合服务,压测时吞吐死活上不去。翻 JFR 发现大量"虚拟线程被 pin 在载体线程上"的事件——罪魁是代码里随处可见的 synchronized。JDK 22/23 的改进,正好把这块骨头啃了下来。 Pin 是什么,为什么是性能杀手 虚拟线程的精
ThreadLocal 在虚拟线程时代水土不服 我们的链路追踪 ID 一直用 ThreadLocal 传。切到虚拟线程后,一个请求一个虚拟线程,数量可能上百万,ThreadLocal 的哈希表跟着膨胀,而且线程复用导致上下文串台——上一个请求的 traceId 漏到了下一个。Java 21 的预览特
等了两年的正式版 JDK 21 在 9 月正式 GA,虚拟线程(Project Loom)终于从预览转正。作为常年和线程池、异步回调搏斗的人,我第一时间把内部一个 IO 密集的采集服务迁了过去。结果不算惊艳到颠覆,但确实把"一个请求一个线程"这种直观写法重新变可行了,迁移成本也比预期低。这里把原理、
解构数据对象的老痛点 做对账时我拿到一个嵌套的支付结果对象,传统写法要一层层 getter 把字段掏出来,还得判空,代码又臭又长。更糟的是改一个字段层级,所有取值点都得跟着改,漏一处就是运行时 NullPointerException,而且这种错编译期发现不了,只能等线上炸。JDK 21 的模式匹配
一个被语法糖耽误的拼接需求 上周我要拼一段带变量的 SQL 调试日志,里面混入三个变量。老写法要么是加号拼接,要么是 String.format,前者冗长后者位置参数容易错位。听同事说 JDK 21 的预览特性 String Templates 把这件事做漂亮了,我拉了 early-access 构
面试被问住:线程池里的异常去哪了 五月面试一个候选人,他反过来问我:「用 ExecutorService 提交了三个任务,其中一个抛异常,另外两个还在跑,怎么保证它们被取消?」我脱口而出「写个 Future 判断」,但细想发现,传统线程池里任务生命周期是散的,取消一个不影响其他——这恰恰是结构化并发
读源码的动机:1 毫秒停顿到底是什么换来的 五月的 JDK 21 EA build 里,分代 ZGC 已经能跑了。官方说停顿能控制在 1 毫秒内。我好奇的是——不分代的 ZGC 已经够强,为什么还要分代?翻了 GC 源码和 JEP 439,才把这件事想明白。 分代假设:大多数对象活不过第一轮 分代回