首页 > Java > java教程 > 正文

在Java中如何使用ConcurrentHashMap实现线程安全的统计表_统计表并发实践

P粉602998670
发布: 2025-10-30 11:58:01
原创
685人浏览过
选择ConcurrentHashMap因它采用分段锁或CAS+synchronized机制,支持高并发读写,避免全局锁性能瓶颈,适用于频繁增删改查的统计场景。

在java中如何使用concurrenthashmap实现线程安全的统计表_统计表并发实践

在高并发场景下,统计表的更新和读取需要保证线程安全。Java 提供了多种方式来实现线程安全的数据结构,其中 ConcurrentHashMap 是最常用且性能较好的选择之一。它不仅支持高并发读写,还能避免使用 synchronized 带来的性能瓶颈

为什么选择 ConcurrentHashMap 实现统计表

普通的 HashMap 不是线程安全的,而 Hashtable 或使用 synchronized 包装的 Map 虽然线程安全,但会锁住整个表,导致并发性能差。ConcurrentHashMap 采用分段锁(JDK 1.8 后改为 CAS + synchronized)机制,允许多个线程同时读取,并在写操作时只锁定局部节点,显著提升并发效率。

对于统计表这类频繁进行 put、get、increment 操作的场景,ConcurrentHashMap 是理想选择。

基本用法:计数统计

最常见的统计需求是记录某个键出现的次数,比如统计用户访问次数、接口调用频次等。

立即学习Java免费学习笔记(深入)”;

示例代码:

ConcurrentHashMap<String, Long> stats = new ConcurrentHashMap<>();

// 线程安全地增加计数
public void increment(String key) {
    stats.merge(key, 1L, Long::sum);
}
登录后复制

merge() 方法是线程安全的:如果 key 不存在,插入初始值 1;存在则执行 Long::sum 将原值加 1。这个操作原子完成,无需额外同步。

也可以使用 compute() 方法实现更复杂的逻辑:

public void incrementWithCompute(String key) {
    stats.compute(key, (k, oldValue) -> oldValue == null ? 1L : oldValue + 1L);
}
登录后复制

进阶用法:多维度统计

实际业务中可能需要维护多个指标,例如每个用户的访问次数和总耗时。

酷表ChatExcel
酷表ChatExcel

北大团队开发的通过聊天来操作Excel表格的AI工具

酷表ChatExcel48
查看详情 酷表ChatExcel

可以定义一个内部类或 record 来封装统计信息:

class StatInfo {
    long count;
    long totalTime;

    public StatInfo(long count, long totalTime) {
        this.count = count;
        this.totalTime = totaltime;
    }
}
登录后复制

然后使用 ConcurrentHashMap 存储复杂对象:

ConcurrentHashMap<String, StatInfo> userStats = new ConcurrentHashMap<>();

public void recordAccess(String userId, long responseTime) {
    userStats.merge(userId,
        new StatInfo(1, responseTime),
        (old, newValue) -> new StatInfo(old.count + 1, old.totalTime + responseTime)
    );
}
登录后复制

这样每次调用都会安全地更新对应用户的统计信息。

性能优化建议

虽然 ConcurrentHashMap 性能优秀,但在极端高并发下仍需注意以下几点:

  • 合理初始化容量和加载因子:避免频繁扩容。例如预估有 1000 个键,可设置初始容量为 1000 / 0.75 ≈ 1333,并向上取最近的 2 的幂(如 16)。
  • 避免长时间持有引用修改 value:不要从 map 中取出对象后在外部长时间处理再放回,可能导致状态不一致。应尽量使用 merge、compute 等原子方法。
  • 考虑使用 LongAdder 替代 Long 类型计数:当计数非常频繁时,JDK 提供的 LongAdder 比 AtomicLong 和普通 long 更快。
使用 LongAdder 示例:

ConcurrentHashMap<String, LongAdder> counterMap = new ConcurrentHashMap<>();

public void incrementFast(String key) {
    counterMap.computeIfAbsent(key, k -> new LongAdder()).increment();
}

public long getCount(String key) {
    LongAdder adder = counterMap.get(key);
    return adder == null ? 0L : adder.sum();
}
登录后复制

LongAdder 在高并发自增场景下通过空间换时间策略降低竞争,读取时再汇总结果,非常适合统计用途。

基本上就这些。ConcurrentHashMap 配合 merge、compute 和 LongAdder,能高效实现线程安全的统计表,既简洁又高性能。

以上就是在Java中如何使用ConcurrentHashMap实现线程安全的统计表_统计表并发实践的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号