You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何ConcurrentHashMap并发put后无法稳定得到预期的1000条记录?

问题分析与解决方案

问题根源

  • 主线程未等待异步任务完成:你提交任务到线程池后,主线程没有等待所有线程执行完put操作就直接打印map的size。ExecutorService.submit()是异步执行的,主线程执行System.out.println(map.size())时,可能还有线程在往map里写数据,此时拿到的是未完成状态的size,自然和预期不符。
  • 这里的问题和ConcurrentHashMap的线程安全性无关,它的put方法本身是线程安全的,相同键的并发put会保证最终值是最后一次写入的结果,但前提是你要等所有写入操作都完成再统计size。

修复后的代码

@Test
public void testThreadSafetyConcurrentHashMap() throws InterruptedException {
    Map<Integer, Integer> map = new ConcurrentHashMap<>();

    Runnable runnable = () -> {
        for (int i = 0; i < 1000; i++) {
            map.put(i, i);
        }
    };

    ExecutorService executorService = Executors.newFixedThreadPool(4);
    for (int i = 0; i < 4; i++) {
        executorService.submit(runnable);
    }

    // 关闭线程池,不再接受新任务
    executorService.shutdown();
    // 等待所有任务执行完成,超时时间设置为10秒(可根据实际调整)
    if (!executorService.awaitTermination(10, TimeUnit.SECONDS)) {
        // 超时后强制关闭线程池
        executorService.shutdownNow();
    }

    System.out.println(map.size()); // 此时会稳定输出1000
}

补充说明

因为四个线程都是对0-999这1000个相同的键执行put操作,ConcurrentHashMap会保证相同键的put操作是原子性的,最终每个键只会保留一个条目,所以所有任务完成后,map的size必然是1000。

内容的提问来源于stack exchange,提问作者tl221

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 07:25:20