为什么我的concurrentSkipListSet在添加多个时添加?

为什么我的concurrentSkipListSet在添加多个时添加?

问题描述:

我想测试ConcurrentSkipListSet对比的ConcurrentLinkedQueue的表现,所以我做了个试验:为什么我的concurrentSkipListSet在添加多个时添加?

ConcurrentSkipListSet<Integer> concurrentSkipListSet=new ConcurrentSkipListSet<>((o1,o2)->{return 1;}); 
HashSet<Callable<Integer>> sets=new HashSet<>(); 
for(int i=0;i<1000;i++){ 
    final int j=i; 
    sets.add(()->{concurrentSkipListSet.add(j); 
     System.out.println(j); 
      return null; 
    }); 
} 
Long c=System.currentTimeMillis(); 
System.out.println(c); 
ExecutorService service=Executors.newFixedThreadPool(10); 
try { 
    service.invokeAll(sets); 
}catch(Exception e){} 
System.out.println(System.currentTimeMillis()-c); 

我很困惑,该方案stucks SOUT后约20〜50焦耳,也不会在完成大约一小时。如果我改变我作为我< 10,它有时在3毫米完成,或有时在东南约4~5 j后完成。

newCachedThreadPool的功能与IDEA和Eclipse中的newFixedThreadPool相同。

请帮助我分析它,3Q。

现在我认为它不是newCachedThreadPool的问题,而是concurrentSkipListSet.add(j); 当我将SkipList更改为LinkedQueue或同步HashSet时,它运行良好,并在168毫秒或170毫秒内完成。

请帮助我分析它,3Q。

问题可能出在您提供给ConcurrentSkipListSet构造函数的比较器中。它总是返回1,这可能会导致在实现ConcurrentSkipListSet时出现某种无限循环。您可以使用不带参数的ConcurrentSkipListSet构造函数来使用Integer的自然排序。

考虑发生了什么事时,你总是从一个比较返回1:“是A大于B”

,我们有两个对象A和B. A在某一点的排序算法可能会问你的比较呼吁compare(A, B)。你返回1,这意味着确实A> B和B应该按排序顺序在A之前。那么在某个时候,算法会问“B比A更大吗?”而你的compare(B, A)也会返回1,这意味着B> A和A应该按照排序顺序在B之前。

你可以看到这个比较器行为是完全不一致的。对于某些算法,这可能会导致无限循环。例如,算法可能会无休止地交换一对元素。

+0

是的,@algrid说的 - ConcurrentSkipList是一个排序后的集合,但是你让所有的值相等,很多(否则高性能)排序算法会遇到困难。尝试它而不提供比较器。 – GregHNZ

+0

@algrid当我想通过添加顺序对元素进行排序时,我应该怎么做而不总是返回1?替换为ConcorrentLinkedQueue?实际上总是返回-1效果不错..... – user8368911

+0

@GregHNZ我尽我所能地阅读了ConcorrectSkipListMap的doPut()的源代码,这是add()中的实用方法。我认为总是“返回1”会使skipList相交。 doPut()可能需要更多时间才能找到合适的位置,但我认为它不会陷入僵局,因为搜索只会停顿或正确。然而,它总是“回归1”而不是变慢。我现在不知道,请帮助我。 – user8368911