2014-05-21 56 views
5

我在讀這本書的「Java SE 8的真的很急」,在第一章我的下一個練習問題碰上了:數組排序方法的行爲

是在數組比較代碼。在調用排序或不同線程的同一線程中調用的排序方法?

我已經在Arrays.sort重載中搜索了javadoc,它使用Comparator參數,但沒有指定任何關於線程的內容。 我認爲,出於性能的原因,該代碼可以在另一個線程中執行,但這只是一個猜測。

+5

它在同一個線程上調用。 –

回答

5

您可以隨時通過登錄Thread.currentThread()id進行測試。

在撥打sort()compare()方法之前添加一些內容。

logger.debug("Thread # " + Thread.currentThread().getId()); 
+2

試過後,它們有效地運行在同一線程 – enrique7mc

4

假設你有代碼來獲取最大的數組中的元素:

int[] array = new int[] {.........}; 
/// Few/many lines of code between... 
Arrays.sort(array); 
int largest = array[array.length - 1]; 

如果排序在另一個線程產生了,你有一個競爭條件 - 將你的數組排序第一,還是將largest分配給第一個?您可以通過鎖定array來避免該問題,但如果您正在運行的代碼已鎖定array,會發生什麼情況?你可以使用join()來阻止原始線程,但是你幾乎擊敗了產生另一個線程的目的,因爲你的代碼的行爲方式與沒有附加線程產生的方式完全相同。

對於Arrays#sort(),排序發生在原始線程中,因爲在產生另一個線程中確實沒有太多意義。您的線程會阻塞,直到排序完成爲止,就像其他任何代碼一樣。

產生另一個線程進行排序的最接近的方法是在Java 8中引入的Arrays#parallelSort()方法。這仍然與常規的Arrays#sort()幾乎相同,因爲它會阻止當前線程,直到排序完成爲止,但有線程在後臺產生以幫助對數組進行排序。對於較大的數據集,我希望圍繞所產生的線程數量有所改善,減去可能存在的線程開銷。

+1

線程會發生在'sort'內部。 'sort'會在返回之前加入它創建的線程。 –

+0

@SotiriosDelimanolis但是對於'sort()',如果你只是想阻止原始線程,那麼產生另一個線程又有什麼意義呢? – awksp

+0

@SotiriosDelimanolis等等,我明白你在說什麼......讓我編輯我的答案。 – awksp

0

在第一次測試中,代碼將以單線程運行。

在第二個測試中,代碼將運行在多個線程中。

@Test 
public void shouldSortInSingleThread() { 

    List<String> labels = new ArrayList<String>(); 
    IntStream.range(0, 50000).forEach(nbr -> labels.add("str" + nbr)); 
    System.out.println(Thread.currentThread()); 
    Arrays.sort(labels.toArray(new String[] {}), (String first, 
      String second) -> { 
     System.out.println(Thread.currentThread()); 
     return Integer.compare(first.length(), second.length()); 

    }); 

} 

@Test 
public void shouldSortInParallel() { 

    List<String> labels = new ArrayList<String>(); 
    IntStream.range(0, 50000).forEach(nbr -> labels.add("str" + nbr)); 

    System.out.println(Thread.currentThread()); 
    Arrays.parallelSort(labels.toArray(new String[] {}), (String first, 
      String second) -> { 
     System.out.println(Thread.currentThread()); 
     return Integer.compare(first.length(), second.length()); 

    }); 

}