Arrays.sort与Arrays.parallelSort

我们都使用Arrays.sort对对象和原始数组进行排序。 该API在下面使用合并排序或Tim排序对内容进行排序,如下所示:

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

即使合并排序使用分而治之技术,所有这些操作都是顺序执行的。 Java 8来了,引入了一个新的API Arrays#parallelSort用于排序。 这是并行进行的排序。 有趣的权利! 让我们看看它是如何做的...

Arrays#parallelSort使用Java 7中引入的Fork / Join框架将排序任务分配给线程池中可用的多个线程。 这被称为吃自己的狗粮 。 Fork / Join实现了一种工作窃取算法,该算法在空闲线程中可以窃取在另一个线程中排队的任务。

Arrays#parallelSort的概述:

该方法使用阈值,并且使用Arrays#sort()API对小于该阈值的任何大小的数组进行排序(即顺序排序)。 并根据机器的并行性,数组大小计算阈值,并计算为:

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 /连接任务,将合并合并的数组。 JDK 8中的实现使用以下方法:
–将阵列分为4部分。
–排序前两个部分,然后将它们合并。 –对接下来的两个部分进行排序,然后将它们合并。 并且对每个零件递归地重复上述步骤,直到要分类的零件的尺寸不小于上面计算的阈值。

一些有趣的结果:

我试图比较Arrays#sort和Arrays#parallelSort在具有4个CPU的计算机上花费的时间。 我用于此比较的程序是:

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);

  }
}

每个API针对不同大小的双精度值数组所花费的时间如下所示:
Table_ParallelSort2
Graph_ParallelSort2

列表也有类似的实现,并且列表上的许多操作具有并行的等效项。

参考:来自Experiences Unlimited博客的JCG合作伙伴 Mohamed Sanaulla的Arrays.sort与Arrays.parallelSort

翻译自: https://www.javacodegeeks.com/2013/04/arrays-sort-versus-arrays-parallelsort.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值