跳到主要内容

JEP 103:并行数组排序

QWen Max 中英对照 人工校对

概述

java.util.Arrays 添加额外的实用方法,这些方法使用 JSR 166 的 Fork/Join 并行通用池来提供数组的并行排序功能。

非目标

有许多用于并行数组排序的算法,它们在时间和空间上有着不同的权衡。这里的目标是提供一个通常有用的实用操作,而不是提供一个让程序员可以选择不同算法的框架。

成功指标

在双核系统上,对于适当大小的数据集,相较于顺序排序,速度提升至少达到 1.3 倍。

动机

Java 7 增加了 Fork/Join 框架以实现轻量级的数据并行处理,但用户目前必须为简单或常见的任务自行实现算法。本提案通过提供数组的并行排序来解决一个常见任务。通过与数组之间的转换,该方法还可以用于对任意集合进行排序(对于那些具有定义好的遍历顺序的集合)。

描述

当前由 Java 集合框架(Collections.sortArrays.sort)提供的排序实现全部在调用线程中按顺序执行排序操作。此增强功能将提供与 Arrays 类当前所提供的相同的一组排序操作,但会使用 Fork/Join 框架的并行实现。这些新的 API 在调用线程方面仍然是同步的,因为在并行排序完成之前,线程不会继续执行后续操作。

该提案新增的实际排序 API 将利用 ForkJoinPool 的 commonPool(默认的 Fork/Join 池由 JEP 155 定义)。

public class Arrays {

...
public static void parallelSort(byte[] a) { ... }
public static void parallelSort(byte[] a, int fromIndex, int toIndex)
public static void parallelSort(short[] a) { ... }
public static void parallelSort(short[] a, int fromIndex, int toIndex)
{...}

...

}

boolean 类型外,所有原始数组类型、Comparable 对象类型以及使用提供的 Comparator 的任意 Object 类型都定义了排序方法。排序算法采用的是 Doug Lea 在 ParallelArray 实现中使用的算法,并且需要一个与待排序数组大小相同的工作空间(这是指整个数组,而不仅仅是待排序的部分)。

开放问题:

  • 一些用户是否需要指定使用哪个池的功能?
  • 用户是否希望选择算法以允许空间/时间的权衡?

替代方案

没有考虑通用的替代方案。并行排序的实现来自于 Doug Lea 的 ParallelArray 框架。已经考虑了 API 的一些变化,特别是关于使用哪个线程池的问题,但目前认为这些变化比实际需要的更为复杂。

测试

  • 包含从 Arrays.sort 的现有测试改编而来的单元测试
  • 还包括展示出比串行排序速度提升的简单基准测试。
  • 性能回归测试需要较大的(8 核以上)系统。

风险与假设

假定选择 Fork/Join 全系统共用的通用池,以及将此 API 与该池关联不会有争议(或者至少不会到阻止本提案进展的程度)。可以在稍后的阶段增加扩展 API 的能力,以允许进一步控制该池。

这里还假设,对于一般使用场景而言,简单的算法选择就足够了。

影响

  • 兼容性:仅向前兼容
  • 安全性:基于共享资源(系统 fork/join 池)提供更多 DoS 攻击
  • 文档:仅提供 Javadoc
  • 国际化:与现有的串行排序相比未改变。