繁体   English   中英

将ConcurrentHashMap复制到HashMap不一致

[英]Copying ConcurrentHashMap to HashMap inconsistency

我正在尝试执行以下操作:

  1. 我的程序启动了线程,这些线程从ConcurrentHashMap<String, AtomicInteger>递增AtomicInteger并将新的Integer添加到ConcurrentHashMap<String, CopyOnWriteArrayList<Integer>> 在这种情况下, CopyOnWriteArrayList的大小等于AtomicInteger的值(当然,对于具有相同键的条目)
  2. 在完成所有线程之后(当CountDownLatch完成时),我尝试将ConcurrentHashMap<String, AtomicInteger>转换为HashMap<String, Integer>以按值对Map进行排序,因为AtomicInteger不具有可比性。
  3. 转换后,我按值对HashMap进行排序,并选择20个具有最高值的条目-在排序的Map中,它们是前20个条目。
  4. 最后,我将值打包在列表中,并使用GSON制作JSON字符串。

问题

我的期望:由于我对AtomicIntegerConcurrentHashMapCopyOnWriteArrayList使用,我期望具有相同键的所有条目的所有大小和值都相等,即使在我的JSON字符串中也是如此:

myAtomcIntegerConcurrentHashMap.get("ABC").intValue() == 
myCOWArrayListConcurrentHashMap.get("ABC").size() == 
myNewHashMap.get("ABC")

但是结果似乎有所不同。 我做了一些控制台输出来测试我的值,并得到以下结果:

ConcurrentHashMap复制到HashMap我再次验证了我的值。 每次“不良复制”值都不同时(有关代码段,请看下面):

 COWArrayList.size  AtomicInteger.intValue  Value in new HashMap
 299                299                     298
 122                122                     121

之后,我对新的HashMap进行了4次以上的迭代,以再次比较我的值,并且每次我得到新的随机“不良复制”值时(注意,复制时未检测到这些值)(有关代码段,请看下面):

 COWArrayList.size  AtomicInteger.intValue  Value in new HashMap  Common Key
 849                849                     827                   CGCCACC
 838                838                     813                   GGTGGTG

我的杰森也不正确。 例如,Json中我数组的键"CGCCACC"大小为887 ,与上表( 849 )不同。

这是我使用的代码片段 (其中一些来自StackOverflow):

在我的线程中增加AtomicInteger并将新的Integer添加到CopyOnWriteArrayList

//Add new Integer 'position' to the COWArrayList from 'positions' with the key 'frame'
List<Integer> copyArr = positions.get(frame);
if (copyArr == null) {
  copyArr = new CopyOnWriteArrayList<Integer>();
  List<Integer> inMap = positions.putIfAbsent(frame, (CopyOnWriteArrayList<Integer>) copyArr);
  if (inMap != null) copyArr = inMap; // already in map
}
copyArr.add(position);

//Increment the AtomicInteger from 'scores' with the key 'frame'
AtomicInteger value = scores.get(frame);
if (value==null){ 
  value = new AtomicInteger();
  AtomicInteger actual = scores.putIfAbsent(frame, value);
  if(actual != null) value = actual;
}
value.incrementAndGet();

ConcurrentHashMap<String, AtomicInteger>复制到HashMap<String, Integer>每个值(我想它的效率很低)并立即进行验证:

//init new, non-concurrent Map
Map<String, Integer> myHashMap = new HashMap<String, Integer>();

//iterate over the Map and copy each value from 'scores' to 'newHashMap'
for(Map.Entry<String, AtomicInteger> score : scores.entrySet()){
  myHashMap.put(score.getKey(), score.getValue().intValue());

  //verify just added Value and print values of all Maps if something is wrong
  if(score.getValue().intValue() != myHashMap.get(score.getKey())){
    System.out.println(score.getValue().intValue() + " " + positions.get(score.getKey()).size() + " " + myHashMap.get(score.getKey()));
  }
}

再次验证myHashMap复制值(在这里我还会获得随机的“不良复制”值):

for(Map.Entry<String, AtomicInteger> score : scores.entrySet()){
  if(score.getValue().intValue() != myHashMap.get(score.getKey())){
  System.out.println(score.getValue().intValue() + " = " + positions.get(score.getKey()).size() + " =? " + myHashMap.get(score.getKey()));
  }
}

为什么会发生这种情况,我是否错过了逻辑上的某些东西?

有关更多信息/代码等-请询问。

感谢你们对我的帮助!

似乎AtomicInteger通过调用AtomicInteger.incrementAndGet()增量事件来查询。 我的线程正在调用该函数〜3.5 Mio次,并且队列很大。 完成我的线程后,主线程立即复制AtomicIntegerConcurrentHashMap ,但是某些AtomicIntegers的队列未完成。 这使得不一致。

我通过在所有线程完成后给AtomicInteger一些时间来完成“增量队列”来解决该问题。

    try {
        myCountDownLatch.await();
        Thread.sleep(5000); //let AtomicInteger finish they incrementations
    } catch (Exception e) {
        System.err.println("Error in a Latch Countdown: " + e.toString());
    }

瞧! 不再有不一致之处!

如果还有另一种方法等待AtomicInteger完成其增量队列,那么我将很乐意阅读有关内容。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM