为什么我的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之前。
你可以看到这个比较器行为是完全不一致的。对于某些算法,这可能会导致无限循环。例如,算法可能会无休止地交换一对元素。
是的,@algrid说的 - ConcurrentSkipList是一个排序后的集合,但是你让所有的值相等,很多(否则高性能)排序算法会遇到困难。尝试它而不提供比较器。 – GregHNZ
@algrid当我想通过添加顺序对元素进行排序时,我应该怎么做而不总是返回1?替换为ConcorrentLinkedQueue?实际上总是返回-1效果不错..... – user8368911
@GregHNZ我尽我所能地阅读了ConcorrectSkipListMap的doPut()的源代码,这是add()中的实用方法。我认为总是“返回1”会使skipList相交。 doPut()可能需要更多时间才能找到合适的位置,但我认为它不会陷入僵局,因为搜索只会停顿或正确。然而,它总是“回归1”而不是变慢。我现在不知道,请帮助我。 – user8368911