Java映射:多线程杂耍者
我面临着以下问题:Java映射:多线程杂耍者,java,multithreading,collections,map,concurrency,Java,Multithreading,Collections,Map,Concurrency,我面临着以下问题: 我有许多异步读者和作者。jdk有没有为我的案例提供线程安全的实现?据我所知,ConcurrentHashMap不适合有许多异步编写器的情况 如果我需要同步彼此之间的两个并发映射,我可以在没有完全同步的情况下实现吗?(我的意思是不在每个方法中添加synchonized关键字) 我读了你的评论,决定重新表述我的问题 想象一下这种情况,您必须: //Singleton public class Container { public ConcurrentHashMap<
我读了你的评论,决定重新表述我的问题 想象一下这种情况,您必须:
//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;
}
}
//单例
公营货柜{
public ConcurrentHashMap map1=新的ConcurrentHashMap();
public ConcurrentHashMap map2=新的ConcurrentHashMap();
公共void replaceForward(字符串键){
对象值=映射1。删除(键);
map2.put(键、值);
}
public void replaceBackward(字符串键){
MyObj值=map2.删除(键);
map1.put(键、值);
}
//此操作应尽可能快!
公共void replaceAllForward(整数标准){
对于(Map.Entry:map1.entrySet()){
if(entry.getValue().criteria=criteria){
replaceForward(entry.getKey());
}
}
}
//此操作应尽可能快!
公共void replaceAllBackward(字符串键){
//相同,但从map2到map1
}
公共无效删除(字符串键){
map1.删除(键);
}
public void add(字符串键,MyObj值){
map2.put(键、值);
}
//此操作应尽可能快!
公共映射getByCriteria(int标准){
ConcurrentHashMap resultMap=新的ConcurrentHashMap();
对于(Map.Entry:map1.entrySet()){
if(entry.getValue().criteria=criteria){
resultMap.put(entry.getKey(),entry.getValue);
}
}
返回结果图;
}
}
您有两个线程,都使用这些映射进行操作
Thread1:将map1
中的元素替换为map2
(我的意思是从map1
中删除并放到map2
)
Thread1:将map2
中的元素替换为map1
问题:它是线程安全的吗?与您的示例中的ConcurrentHashMap类似,如果您编写:
V value = map1.remove(key);
if (value != null) map2.put(key, value);
您可以保证不会有任何项目“丢失”,也不会有任何项目被多次添加到map2,即使存在多个读写器
但是,在很短的时间内,键/值将不在map1或map2中。对于您的用例来说,这可能是问题,也可能不是问题
在replaceAllForward
中,您迭代一个映射并将内容移动到另一个映射。在这里,移动将安全地进行,但如果同时添加了一些项目,则可能会在原始地图的末尾留下一些项目
如何使
getAllByCriteria
更快
这取决于你地图的大小。如果它很小的话,你可能不会做得更好。如果它更大,您可以将作业并行化
使用Java 8,您可能会通过以下方式获得更好的性能:
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));
}
publicmap getByCriteria(int-criteria){
返回map1.entrySet()
.parallelStream()//这是您的加速比
.filter(e->e.getValue().criteria=标准)
.collect(toConcurrentMap(Entry::getKey,Entry::getValue));
}
在Java 8之前,您可以自己编写并行算法,看看它是否能提高性能。“ConcurrentHAshMap不适合有许多异步编写器的情况。”=>您为什么会这样想?请详细说明2中的含义。?地图之间的关系是什么?@assylias我刚听说。我错了吗?@VolodymyrBakhmatiuk ConcurrentHashMap正是为此而设计的:多个读写器。现在的问题是这是否是原子的,不是吗?1)你的意思是它是绝对线程安全的吗?2) 如何使
getAllByCriteria
更快?@VolodymyrBakhmatiuk这再次取决于您需要什么样的线程安全性。如果您需要确保条目始终位于map1或map2中,则不安全。如果您确定在移动时,条目既不在map1中也不在map2中,那么它是安全的。换句话说,这取决于类的不变量应该是什么。@VolodymyrBakhmatiuk关于第二个问题,请参阅我的编辑。谢谢解释。不可以实体既不在map1中也不在map2中是不可以的。我该怎么办?也许有一种方法可以将这两张地图表示为一张?(但在这种情况下,我必须有一种快速的方法从求和映射中提取submap1和submap2)如果不锁定,我看不到明显的解决方案。。。你可以围绕这个具体问题问一个新问题。