惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - 叶小钗
J
Java Code Geeks
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
阮一峰的网络日志
阮一峰的网络日志
爱范儿
爱范儿
量子位
N
Netflix TechBlog - Medium
博客园 - 聂微东
博客园 - Franky
aimingoo的专栏
aimingoo的专栏
The Cloudflare Blog
T
The Blog of Author Tim Ferriss
MyScale Blog
MyScale Blog
Google DeepMind News
Google DeepMind News
小众软件
小众软件
博客园 - 三生石上(FineUI控件)
C
Check Point Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
B
Blog
Engineering at Meta
Engineering at Meta
Microsoft Azure Blog
Microsoft Azure Blog
博客园_首页
H
Hackread – Cybersecurity News, Data Breaches, AI and More
腾讯CDC

博客园 - buguge

交易成功还要记 3 笔账?我们直接砍到 1 笔—— 网络红包记账的一次自顶向下业务层重构 分享一次针对hardcode的小重构:不要把 package 名写死在代码里 聚合系统设计:如何为银行代付通道抽象出公共的代付接口能力 如何自定义 MyBatis枚举处理器(EnumTypeHandler):分享从 “同包同名 shadow 覆盖” 到 “官方扩展点” 的重构经历 这儿也改状态,那儿也改状态,连AI都理不清楚了… 不妨试试这个状态机good-practice 业务解耦的经典实践:从订单表解耦开票业务说起(以滴滴网约车开票为例) 从 `int` 到 `Duration`:一个缓存 API 的三次演进教会我的事 最差实践(bad-practice):开发者在方法里直接实例化线程池对象,然后...(应用gg了) 【HttpClient最差实践(bad-practice)】开发者在 http 工具方法中直接实例化 HttpClient,然后…… Crypto、Cipher与Password:Java加密开发的三个核心概念 知识VS技能:如何优雅判空? 20260604SR超时问题排查 推敲见文章:从 `try..catch` 看异常日志打印的正确姿势 #解决问题要彻底# 慢SQL治理完成后,如何防止同类问题“死灰复燃”? 从合同甲方是荒谬的“JD”谈起:软件开发不应遗忘的“常识” 别留小尾巴/尽快剪掉小尾巴:从一次“ABA”字段重命名,谈谈“解决问题要彻底” 常见的OOM错误 ( OutOfMemoryError全类型详解) 开发者暴露了一个无需授权访问的裸接口,我问:如果有人暴力请求怎么办? 【SQL性能优化篇】有了!治理慢SQL“WHERE create_time ORDER BY id”的良药---规避“Using filesort”性能杀手 高效查询商户日终余额:一个SQL的优化实践 Hutool 的 `TimedCache` 到期会自动清理吗? ——————hutool cache的"惰性清理"和"定期清理" Fastjson枚举反序列化:当字符串不是枚举常量名时,会发生什么? fastjson-EnumDeserializer类及源码分析 随笔20260309:我们都是围城里的人 `UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only` 异常解析 认识2个单词:goal/target —————— 为什么Maven是 "goal" 而不是 "target"? 聚合系统设计:策略模式(Strategy Pattern)在银行通道对接场景中的应用 这样构建对象,太帅了!—— 阶梯式Builder模式与代码整洁之道 注意!字段数据类型不匹配,这个sql会很慢 还在用ArrayList?用HashSet吧!--性能对比
从 synchronized 到 ConcurrentHashMap:一个小小的并发控制...
buguge · 2026-02-04 · via 博客园 - buguge

我们是SpringBoot+Mybatisplus项目。我的一个工具方法中,需要获取entity对象对应数据表的 “更新时间” 字段名(update_time 或 updateTime)。

代码完成后,考虑到其中的Mybatisplus调用及java反射机制所产生的性能损耗,我使用Map来缓存数据关系。

其中,考虑到并发调用,我随即在方法上加了synchronized

private static Map<Class, String> updateTimeColumnMap = new HashMap<>();

/**
 * 获取updateTime字段
 */
private synchronized static <Entity> String getUpdateTimeColumn(Class<Entity> clz) {
    String updateTimeColumn = updateTimeColumnMap.get(clz);
    if (updateTimeColumn == null) {
        TableInfo tableInfo = TableInfoHelper.getTableInfo(clz);
        List<TableFieldInfo> fieldList = tableInfo.getFieldList();
        if (fieldList.stream().anyMatch(p -> p.getColumn().contentEquals("update_time"))) {
            updateTimeColumn = "update_time";
        }
        if (fieldList.stream().anyMatch(p -> p.getColumn().contentEquals("updateTime"))) {
            updateTimeColumn = "updateTime";
        }
        updateTimeColumnMap.put(clz, updateTimeColumn);
    }
    return updateTimeColumn;
}

晚上下班后“无丝竹之乱耳”,我又开始琢磨并发调用的问题,因为我知道 synchronized 锁的粒度比较粗,会影响性能。
发给AI后,立即给了我答案。很简单,利用 ConcurrentHashMap 的原子方法 computeIfAbsent来保证线程安全,无需显式加锁。基于CAS和无锁编程,这是最直接和高效的改进方式。

不得不说妙极了!当然,此前也有使用 ConcurrentHashMap,只恨书到用时方恨少。确切地说,是没深刻掌握。

private static Map<Class, String> updateTimeColumnMap = new ConcurrentHashMap<>();

private static <Entity> String getUpdateTimeColumn(Class<Entity> clz) {
    return updateTimeColumnMap.computeIfAbsent(clz, key -> {
        TableInfo tableInfo = TableInfoHelper.getTableInfo(clz);
        List<TableFieldInfo> fieldList = tableInfo.getFieldList();
        
        String columnName = null;
        if (fieldList.stream().anyMatch(p -> "update_time".equals(p.getColumn()))) {
            columnName = "update_time";
        } else if (fieldList.stream().anyMatch(p -> "updateTime".equals(p.getColumn()))) {
            columnName = "updateTime";
        }
        // 如果未找到,这里会缓存null,可考虑缓存空字符串""或一个特定的标识
        return columnName; 
    });
}

从一种较重的“互斥锁”模式,升级为一种更轻量的“无锁编程”模式,这一次并发控制策略的升级CASE,也许证明我还停留在初级编程阶段。

知识就是力量,但更重要的,是..

在编程道路上,比学习新知识更重要的,是不断审视和改进已有的解决方案。即使一个功能已经“能用”,也要多问自己一句:“它能‘更好’吗?有没有更简洁、更高效、更优雅的实现方式?”

这份不甘于“够用就好”的劲头,驱动着我们从初级程序员一步步向前迈进。