我想测试ConcurrentSkipListSet与ConcurrentLinkedQueue的性能,所以我做了一个测试:
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);
我很困惑,该程序在sout约20~50 j之后停留,并且在大约一个小时内无法完成。如果我将i更改为i&lt; 10,它有时会以3毫秒结束,或者在sout约4~5 j之后卡住。
newCachedThreadPool perfroms与IDEA和Eclipse中的newFixedThreadPool相同。
请帮我分析一下,3Q。
现在我认为这不是newCachedThreadPool的问题,而是concurrentSkipListSet.add(j); 当我将SkipList更改为LinkedQueue或同步HashSet时,它运行良好并以168毫秒或170毫秒完成。
请帮我分析一下,3Q。
答案 0 :(得分:1)
问题可能出在您提供给ConcurrentSkipListSet
构造函数的比较器中。它总是返回1,这可能导致ConcurrentSkipListSet
实现中的某种无限循环。您可以使用不带参数的ConcurrentSkipListSet
构造函数来使用Integer
的自然顺序。
考虑当你总是从比较器返回1时会发生什么:
假设我们有两个对象A和B.某个点的排序算法可能会让你的比较器“比A大吗?”致电compare(A, B)
。你返回1表示确实A&gt; B和B应按排序顺序排在A之前。那么在某些时候,算法有可能会问“B大于A吗?”并且您的compare(B, A)
也会返回1,这意味着B&gt; A和A应按排序顺序排在B之前。
您可以看到此比较器行为完全不一致。对于某些算法,这可能会导致无限循环。例如,算法可以无休止地交换一对元素。