2017-08-27 106 views
1

我想測試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。

回答

1

問題可能出在您提供給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

相關問題