问题描述
我遇到了下列问题:
- 我有许多异步阅读器和写入器。有jdk有任何实现提供线程安全我的情况吗?根据我的理解ConcurrentHashMap不适用于有许多异步写入的情况。
- 如果我需要同步两个并发映射,我可以实现没有完全同步吗? (我的意思是没有在每种方法中添加synchonized关键字)
决定改写我的问题。
I read your comments and decided to reformulate my question.
想象一下,你必须有并发地图:
Imagine situation, you have to concurrent maps:
//Singleton
public class Container {
public ConcurrentHashMap<String, MyObj> map1 = new ConcurrentHashMap<String, MyObj>();
public ConcurrentHashMap<String, MyObj> map2 = new ConcurrentHashMap<String, MyObj>();
public void replaceForward(String key) {
Object value = map1.remove(key);
map2.put(key, value);
}
public void replaceBackward(String key) {
MyObj value = map2.remove(key);
map1.put(key, value);
}
//This operation should be as quick as possible!
public void replaceAllForward(int criteria) {
for (Map.Entry<String, MyObj> entry entry : map1.entrySet()) {
if (entry.getValue().criteria = criteria) {
replaceForward(entry.getKey());
}
}
}
//This operation should be as quick as possible!
public void replaceAllBackward(String key) {
//just the same but from map2 to map1
}
public void remove(String key) {
map1.remove(key);
}
public void add(String key, MyObj value) {
map2.put(key, value);
}
//This operation should be as quick as possible!
public Map<String, MyObj> getByCriteria(int criteria) {
ConcurrentHashMap<String, MyObj> resultMap = new ConcurrentHashMap<String, MyObj>();
for (Map.Entry<String, MyObj> entry entry : map1.entrySet()) {
if (entry.getValue().criteria = criteria) {
resultMap.put(entry.getKey(), entry.getValue);
}
}
return resultMap;
}
}
你有两个线程,
Thread1:将 map1
的元素替换为 map2
(我的意思是从中移除map1
,并将 map2
)
Thread1: replaces elements from map1
to map2
(i mean removes from map1
and puts to map2
)
Thread1:将元素从 map2
替换为 map1
问题: 线程是否安全?
Question: Is it thread safe?
推荐答案
使用ConcurrentHashMap类似于您的示例,并且如果您写:
With ConcurrentHashMap like in your example and if you write:
V value = map1.remove(key);
if (value != null) map2.put(key, value);
您保证没有项目会丢失,并且没有项目将被添加到map2更多
you have the guarantee that no item will get "lost" and no item will be added to map2 more than once, even in the presence of multipler readers/writers.
然而,会有一个很短的时间,在这段时间内,键/值不会出现在map1或map2中。
However there is going to be a short time during which the key/value will not be in map1 or map2. This may or may not be a problem for your use case.
在您的 replaceAllForward
中,您可以迭代一个地图和将内容移动到其他地图。这里再次,移动会安全地进行,但如果在此期间添加了原始地图,则可能会在原始地图中留下一些项目。
In your replaceAllForward
you iterate over one map and move the content to the other map. Here again, the move will happen safely, but there may be some items left in the original map at the end if they have been added in the meantime.
这取决于地图的大小。如果它是小型的,你可能不能做得更好。
It depends on the size of your map. If it's small-ish, you probably can't do much better. If it is larger, you can parallelise the job.
对于Java 8,你可能会得到更好的性能:
With Java 8, you could probably get a better performance with something like:
public Map<String, MyObj> getByCriteria(int criteria) {
return map1.entrySet()
.parallelStream() //this is your speedup
.filter(e -> e.getValue().criteria = criteria)
.collect(toConcurrentMap(Entry::getKey, Entry::getValue));
}
在Java 8之前,您可以自己编写并行算法,提高了性能。
Prior to Java 8, you could write the parallel algo yourself and see if it improves the performance.
这篇关于Java映射:多线程juggler的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!