Java8 Arrays.sort VS Arrays.parallelSort


開發者都會用到Arrays.sort來對原生數組進行排序,這個API會使用歸並排序或者Tim排序來進行排序,源碼如下所示:

public static void sort(Object[] a) {
  if (LegacyMergeSort.userRequested)
      legacyMergeSort(a);
  else
      ComparableTimSort.sort(a);
}

上面的代碼會依次執行,歸並排序使用了分治的技術。

Java8出來之后,有一個新API用來進行排序,這就是Arrays.ParallelSort,這是一種並行排序,讓我們來看看它是怎么實現的。

Arrays.ParallelSort使用了Java7的Fork/Join框架使排序任務可以在現場池中的多個線程中進行,Fork/Join實現了一種任務竊取算法,一個閑置的線程可以竊取其他線程的閑置任務進行處理。

 

Arrays.parallelSort概述

這個方法使用了一個臨界值,還有一些容量小於這個臨界值的數組,這個臨界值和數組的容量都是計算來用於並行計算的,如下代碼所示:

private static final int getSplitThreshold(int n) {
  int p = ForkJoinPool.getCommonPoolParallelism();
  int t = (p > 1) ? (1 + n / (p << 3)) : n;
  return t < MIN_ARRAY_SORT_GRAN ? MIN_ARRAY_SORT_GRAN : t;
}

一旦數組決定了使用並行排序,那他馬上會被分為幾個部分,然后通知Fork/Join任務對各個部分進行排序,跟着通知另外的Fork/Join任務對排序后的數組進行合並。

Java8使用如下的方法進行實現:

1、將數組分成4個子數組。

2、對前面兩個子數組進行排序然后合並。

3、對后面的兩個進行排序然后合並。

上面着幾個步驟會重復遞歸,每個子數組都要求容量小於上面計算出來的臨界值。

 

對比結果

我嘗試去對比Arrays.sort和Arrays.parallelSort的排序時間,在一台4CPU的電腦上,使用如下的代碼:

 
public class ArraysParallelDemo {
  public static void main(String[] args) throws FileNotFoundException {
    List<Double> arraySource = new ArrayList<>();
 
    Scanner reader = new Scanner(ClassLoader.
        getSystemResourceAsStream("java8demo/large_array_input"));
    while(reader.hasNext()){
      String line = reader.nextLine();
      String[] strNums = line.split(",");
      for ( String strN : strNums){
          arraySource.add(Double.parseDouble(strN));
      }
    }
 
    System.out.println(arraySource.size());
 
    Double [] myArray = new Double[1];
    myArray = arraySource.toArray(myArray);
    long startTime = System.currentTimeMillis();
    Arrays.sort(myArray);
    long endTime = System.currentTimeMillis();
    System.out.println("Time take in serial: "+
        (endTime-startTime)/1000.0);
 
    Double [] myArray2 = new Double[1];
    myArray2 = arraySource.toArray(myArray);
    startTime = System.currentTimeMillis();
    Arrays.parallelSort(myArray2);
    endTime = System.currentTimeMillis();
    System.out.println("Time take in parallel: "+
        (endTime-startTime)/1000.0);
 
  }
}

數組容量和時間消耗的一個基准測試如下所示:


在數組容量小於10000的情況下,並行排序和串行排序消耗時間是差不多的,但是當數組容量在10000以上的時候,並行排序就體現出了它的優勢。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM