在Java高并发环境下,实现线程安全的List和Map有以下几种常见方案

一、线程安全List

1. 同步包装类
复制代码
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
  • 通过synchronized方法实现线程安全

  • 迭代时需要手动加锁

  • 适合低并发场景

2. CopyOnWriteArrayList(推荐)
复制代码
List<String> copyList = new CopyOnWriteArrayList<>();
  • 写时复制:修改时创建新数组,读操作无锁

  • 适合读多写少场景

  • 迭代器是快照,不会抛出ConcurrentModificationException

3. Vector(已过时)
复制代码
Vector<String> vector = new Vector<>();
  • JDK1.0遗留类,方法使用synchronized修饰

  • 性能较差,不推荐使用


二、线程安全Map

1. ConcurrentHashMap(推荐)
java 复制代码
Map<String, Object> concurrentMap = new ConcurrentHashMap<>();
  • JDK1.7:分段锁(Segment)

  • JDK1.8+:synchronized+ CAS + 红黑树

  • 高并发下性能优秀

  • 不允许null键/值

2. Collections.synchronizedMap
java 复制代码
Map<String, Object> syncMap = Collections.synchronizedMap(new HashMap<>());
  • 使用synchronized包装所有方法

  • 迭代时需要手动同步

3. ConcurrentSkipListMap
java 复制代码
Map<String, Object> skipMap = new ConcurrentSkipListMap<>();
  • 基于跳表实现的有序并发Map

  • 支持范围查询

4. Hashtable(已过时)
java 复制代码
Hashtable<String, Object> table = new Hashtable<>();
  • 与Vector类似,全表锁性能差

三、选择策略

场景 List推荐方案 Map推荐方案
读多写少 CopyOnWriteArrayList ConcurrentHashMap
写多读少 Collections.synchronizedList ConcurrentHashMap
需要有序 - ConcurrentSkipListMap
低并发 同步包装类 同步包装类

四、注意事项

  1. 复合操作问题

    java 复制代码
    // 即使使用ConcurrentHashMap,以下操作仍然非原子
    if (!map.containsKey(key)) {
        map.put(key, value); // 可能存在竞态条件
    }
    // 应使用
    map.putIfAbsent(key, value);
  2. 迭代器弱一致性

    • 并发集合的迭代器是弱一致

    • 不保证迭代时看到所有更新

  3. 性能考量

    • CopyOnWriteArrayList写操作昂贵(复制数组)

    • ConcurrentHashMap扩容时效率较高


五、JDK8+增强

java 复制代码
// ConcurrentHashMap的原子操作
concurrentMap.computeIfAbsent(key, k -> createValue(k));
concurrentMap.merge(key, value, (oldVal, newVal) -> mergeFunction(oldVal, newVal));

// 批量操作
concurrentMap.forEach(parallelismThreshold, action);
concurrentMap.search(parallelismThreshold, searchFunction);

最佳实践

  1. 优先使用java.util.concurrent包下的并发集合

  2. 明确业务场景的读写比例

  3. 使用原子方法避免复合操作竞态条件

  4. 考虑使用ThreadLocal减少竞争

  5. 高并发场景避免使用Collections.synchronizedXXX

高并发环境下线程安全的去重List实现方案

一、核心解决方案

1. 使用 CopyOnWriteArraySet

java 复制代码
Set<String> uniqueSet = new CopyOnWriteArraySet<>();
// 自动去重,线程安全
uniqueSet.add("item1");
uniqueSet.add("item1"); // 不会被添加

特点

  • 内部使用CopyOnWriteArrayList实现

  • 添加时会遍历检查是否已存在(O(n)复杂度)

  • 适合读多写少的场景

  • 保证元素唯一性

2. 使用 ConcurrentHashMap 模拟去重List

java 复制代码
// 使用ConcurrentHashMap模拟去重List
Map<String, Boolean> map = new ConcurrentHashMap<>();
List<String> list = Collections.synchronizedList(new ArrayList<>());

public boolean addIfAbsent(String item) {
    if (map.putIfAbsent(item, Boolean.TRUE) == null) {
        list.add(item);
        return true;
    }
    return false;
}
相关推荐
独自破碎E几秒前
SLKJ笔试题解析
java·开发语言
Lsland..2 分钟前
AI Agent到底是什么
java·人工智能·llm
Halo_tjn2 分钟前
JDBC 技术的使用
java·算法
aaaffaewrerewrwer1 小时前
一个真正“完全浏览器本地运行”的 AVIF 转 WebP 在线工具(无需上传)
安全·个人开发
ps酷教程8 小时前
Jackson 解决没有无参构造函数的反序列化问题
java
NiceCloud喜云8 小时前
Opus 4.8 的 Effort Control 怎么选:Low 到 Max 五档策略
android·java·大数据·前端·c++·python·spring
ylscode9 小时前
PureLogs 信息窃取恶意软件惊现高危变种:借道 MsBuild.exe 进程空心化实施无痕攻击
网络·安全·安全威胁分析
_日拱一卒9 小时前
LeetCode:994腐烂的橘子
java·数据结构·算法·leetcode·深度优先
云安全助手9 小时前
2026年企业级Claude中转服务深度评测:安全、稳定与速度的终极答案
人工智能·安全·claude·ai大模型
隔窗听雨眠9 小时前
Nginx网关响应慢排查手记
java·服务器·nginx