Reputation: 45702
I faced the next problems:
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;
}
}
And you have two threads, both operates with those maps.
Thread1: replaces elements from map1
to map2
(i mean removes from map1
and puts to map2
)
Thread1: replaces elements from map2
to map1
Question: Is it thread safe?
Upvotes: 0
Views: 202
Reputation: 328737
With ConcurrentHashMap like in your example and if you write:
V value = map1.remove(key);
if (value != null) map2.put(key, value);
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.
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.
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.
How to make
getAllByCriteria
faster?
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.
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));
}
Prior to Java 8, you could write the parallel algo yourself and see if it improves the performance.
Upvotes: 1