假设我有一个 Java Hashmap,其中键是字符串或其他内容,值是其他值的列表,例如
Map<String,List<String>> myMap=new HashMap<String,List<String>>();
//adding value to it would look like this
myMap.put("catKey", new ArrayList<String>(){{add("catValue1");}} );
如果我们有许多线程在列表中添加和删除值(不更改键,只是更改 HashMap 的值),是否有办法使对列表的访问仅是线程安全的?这样多个线程可以同时编辑多个值?
最佳答案
使用同步或并发列表实现而不是 ArrayList
,例如
new Vector()
(已同步)new ConcurrentLinkedDeque<>()
(并发,不是List
)
最后一个不是列表,但如果您实际上不需要按索引访问(即随机访问),则很有用,因为它的性能比其他列表更好。
<小时/>请注意,由于您可能需要将初始空列表并发插入到新键的映射中,因此您应该使用 ConcurrentHashMap
对于Map
本身,而不是简单的 HashMap
.
建议
Map<String, Deque<String>> myMap = new ConcurrentHashMap<>();
// Add new key/value pair
String key = "catKey";
String value = "catValue1";
myMap.computeIfAbsent(key, k -> new ConcurrentLinkedDeque<>()).add(value);
上面的代码在向映射添加新键时是完全线程安全的,在向列表添加新值时也是完全线程安全的。该代码不会花费时间获取同步锁,并且不会遭受 CopyOnWriteArrayList
所带来的性能下降。当列表变大时有。
唯一的问题是它使用 Deque
,不是List
,但实际情况是 List
的大多数用途可以很容易地使用 Deque
,但指定 List
出于习惯,所以这可能是一个可以接受的改变。
关于java - 如何同步访问 Java Hashmap 中的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60468312/