将concurrenthashmap复制到hashmap不一致

f0ofjuux  于 2021-07-09  发布在  Java
关注(0)|答案(1)|浏览(398)

我正在努力做到以下几点:
我的程序启动线程,它以 AtomicIntegerConcurrentHashMap<String, AtomicInteger> 并添加新的 IntegerConcurrentHashMap<String, CopyOnWriteArrayList<Integer>> . 如果是那样的话 CopyOnWriteArrayList 等于 AtomicInteger (当然,对于具有相同键的条目)
所有线程完成后(当 CountDownLatch 完成)我尝试转换 ConcurrentHashMap<String, AtomicInteger> 进入 HashMap<String, Integer> 按值对Map排序,因为 AtomicInteger 是不可比的。
转换后我将 HashMap 按值选择20个值最高的条目-在排序的Map中,它们是前20个条目。
最后,我将值打包到一个列表中,并使用gson生成json字符串。
问题
我期待的是:由于我使用了 AtomicInteger , ConcurrentHashMap 以及 CopyOnWriteArrayList 我希望具有相同键的所有条目的所有大小和值都相等,即使在我的json字符串中,例如:

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

但结果似乎不同。我做了一些控制台输出来测试我的值,得到了以下结果:
从复制时 ConcurrentHashMapHashMap 我再次验证我的价值观。每次“错误复制”值不同时(对于下面的代码段):

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

之后,我在新的 HashMap 要再次比较我的值,以及每次获得新的随机“错误复制”值时(请注意,复制时未检测到这些值)(对于下面的代码段,请查看):

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

我的json也不正确。e、 g.钥匙 "CGCCACC" 我的json数组的大小是 887 ,与上表不同( 849 ).
以下是我使用的代码片段(其中一些来自stackoverflow):
递增 AtomicInteger 并将新整数添加到 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()));
  }
}

为什么会发生这样的事,我的逻辑有什么遗漏吗?
更多信息/代码等-请询问。
谢谢你帮助我!

mbskvtky

mbskvtky1#

看来 AtomicInteger 打电话询问 AtomicInteger.incrementAndGet() 增量事件。我的线程调用该函数的次数约为350万次,而且队列非常庞大。线程完成后,主线程立即复制 ConcurrentHashMapAtomicInteger ,但是一些 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 完成他们的增量队列,我会很感激读到这一点。

相关问题