Java 8引入了一个API来解决这个确切的问题,提出了一种1行解决方案:
public void record(String key, String value) { entries.computeIfAbsent(key, k -> Collections.synchronizedList(new ArrayList<String>())).add(value);}对于Java 7:
public void record(String key, String value) { List<String> values = entries.get(key); if (values == null) { entries.putIfAbsent(key, Collections.synchronizedList(new ArrayList<String>())); // At this point, there will definitely be a list for the key. // We don't know or care which thread's new object is in there, so: values = entries.get(key); } values.add(value);}这是填充时的标准代码模式
ConcurrentHashMap。
特殊方法
putIfAbsent(K,V))将放入您的值对象,或者如果在您之前有另一个线程,那么它将忽略您的值对象。无论哪种方式,都确保在调用之后
putIfAbsent(K,V)),
get(key)线程之间保持一致,因此上述代码是线程安全的。
唯一浪费的开销是,如果其他某个线程在同一时间为同一键同时添加新条目:您 可能 最终 会 丢弃新创建的值,但这只会在尚无条目 且
存在种族冲突的情况下发生线程丢失,这种情况通常很少见。



