为什么我的 concurrentSkipListSet 在 multi add 时卡住了?
Why my concurrentSkipListSet stucks while multi add?
我想测试一下 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<10,它有时会以 3 毫秒完成,或者有时会在 sout 后卡住大约 4~5 j。
一个newCachedThreadPool,与IDEA和Eclipse中的newFixedThreadPool一样。
请帮我分析一下,3Q。
现在我认为这不是 newCachedThreadPool 的问题,而是 concurrentSkipListSet.add(j);
当我将 SkipList 更改为 LinkedQueue 或同步的 HashSet 时,它运行良好并在 168 毫秒或 170 毫秒内完成。
请帮我分析一下,3Q。
问题可能出在您提供给 ConcurrentSkipListSet
构造函数的比较器中。它总是 returning 1 这可能会导致 ConcurrentSkipListSet
实现中的某种无限循环。您可以使用不带参数的 ConcurrentSkipListSet
构造函数来对 Integer
.
使用自然排序
考虑一下当您总是从比较器 returning 1 时发生了什么:
假设我们有两个对象 A 和 B。排序算法在某个时候可能会要求您的比较器 "is A greater then B?" 调用 compare(A, B)
。你 return 1 这意味着确实 A > B 并且 B 应该按排序顺序排在 A 之前。然后在某个时候,算法有可能会询问 "is B greater then A?" 而你的 compare(B, A)
也会 return 1 这意味着 B > A 并且 A 应该按排序顺序排在 B 之前。
你可以看到这个比较器的行为是完全不一致的。对于某些算法,这可能会导致无限循环。例如,一个算法可能会无休止地交换一对元素。
我想测试一下 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<10,它有时会以 3 毫秒完成,或者有时会在 sout 后卡住大约 4~5 j。
一个newCachedThreadPool,与IDEA和Eclipse中的newFixedThreadPool一样。
请帮我分析一下,3Q。
现在我认为这不是 newCachedThreadPool 的问题,而是 concurrentSkipListSet.add(j); 当我将 SkipList 更改为 LinkedQueue 或同步的 HashSet 时,它运行良好并在 168 毫秒或 170 毫秒内完成。
请帮我分析一下,3Q。
问题可能出在您提供给 ConcurrentSkipListSet
构造函数的比较器中。它总是 returning 1 这可能会导致 ConcurrentSkipListSet
实现中的某种无限循环。您可以使用不带参数的 ConcurrentSkipListSet
构造函数来对 Integer
.
考虑一下当您总是从比较器 returning 1 时发生了什么:
假设我们有两个对象 A 和 B。排序算法在某个时候可能会要求您的比较器 "is A greater then B?" 调用 compare(A, B)
。你 return 1 这意味着确实 A > B 并且 B 应该按排序顺序排在 A 之前。然后在某个时候,算法有可能会询问 "is B greater then A?" 而你的 compare(B, A)
也会 return 1 这意味着 B > A 并且 A 应该按排序顺序排在 B 之前。
你可以看到这个比较器的行为是完全不一致的。对于某些算法,这可能会导致无限循环。例如,一个算法可能会无休止地交换一对元素。