Java 合并排序算法的工作线程实现

Java 合并排序算法的工作线程实现,java,multithreading,mergesort,Java,Multithreading,Mergesort,我有一个单线程版本的合并排序 它创建一个数组,用随机数填充,并调用对其执行合并排序的排序方法: private static int[] sort(int[] array) { //TODO: use multiple threads to speed up the sorting return mergeSort(array, 0, array.length); } 现在我想在java中使用多线程技术来提高性能。代码来自我的导师,他说我必须在排序方法中添加一些东西,但这实际

我有一个单线程版本的合并排序

它创建一个数组,用随机数填充,并调用对其执行合并排序的排序方法:

private static int[] sort(int[] array) {
    //TODO: use multiple threads to speed up the sorting

    return mergeSort(array, 0, array.length);
}
现在我想在java中使用多线程技术来提高性能。代码来自我的导师,他说我必须在排序方法中添加一些东西,但这实际上让我感到困惑

合并排序是一种分而治之的算法:

  • 如果列表的长度为0或1,则该列表已排序。否则:
  • 将未排序的列表分成两个子列表,大小约为一半
  • 通过重新应用合并排序对每个子列表进行递归排序
  • 将两个子列表合并回一个排序列表

所以我实际上会为每个子列表启动一个线程。你怎么认为?如何根据给定的实现并行化合并排序?有人知道我为什么要编辑排序方法吗?

这是一个很好的练习,可以在Java 7.0中使用set to release。这正是你要找的。您只需将(fork)递归合并任务提交到池中,并在完成后加入结果

你可以下载。关于更多信息,这是一篇很好的文章

编辑以回应您的评论:

如果您想自己实现它,那么您就不希望每个子列表都有一个新线程。您可以想象一个给定数组将有许多分区需要排序,因此每个分区的线程将增长巨大(假设一个足够大的数组)。相反,您可能希望为实际执行合并工作的每个分区数组都有一个线程。ForkJoin为您做到了这一点,使用FJ池的好处之一是它将重用线程,而不是为子进程合并创建新线程。

在java 7中使用类

public class ParallelMergeSort {

private static final ForkJoinPool threadPool = new ForkJoinPool();
private static final int SIZE_THRESHOLD = 16;

public static void sort(Comparable[] a) {
    sort(a, 0, a.length-1);
}

public static void sort(Comparable[] a, int lo, int hi) {
    if (hi - lo < SIZE_THRESHOLD) {
        insertionsort(a, lo, hi);
        return;
    }

    Comparable[] tmp = new Comparable[a.length];
    threadPool.invoke(new SortTask(a, tmp, lo, hi));
}

/**
 * This class replaces the recursive function that was
 * previously here.
 */
static class SortTask extends RecursiveAction {
    Comparable[] a;
    Comparable[] tmp;
    int lo, hi;
    public SortTask(Comparable[] a, Comparable[] tmp, int lo, int hi) {
        this.a = a;
        this.lo = lo;
        this.hi = hi;
        this.tmp = tmp;
    }

    @Override
    protected void compute() {
        if (hi - lo < SIZE_THRESHOLD) {
            insertionsort(a, lo, hi);
            return;
        }

        int m = (lo + hi) / 2;
        // the two recursive calls are replaced by a call to invokeAll
        invokeAll(new SortTask(a, tmp, lo, m), new SortTask(a, tmp, m+1, hi));
        merge(a, tmp, lo, m, hi);
    }
}

private static void merge(Comparable[] a, Comparable[] b, int lo, int m, int hi) {
    if (a[m].compareTo(a[m+1]) <= 0)
        return;

    System.arraycopy(a, lo, b, lo, m-lo+1);

    int i = lo;
    int j = m+1;
    int k = lo;

    // copy back next-greatest element at each time
    while (k < j && j <= hi) {
        if (b[i].compareTo(a[j]) <= 0) {
            a[k++] = b[i++];
        } else {
            a[k++] = a[j++];
        }
    }

    // copy back remaining elements of first half (if any)
    System.arraycopy(b, i, a, k, j-k);

}

private static void insertionsort(Comparable[] a, int lo, int hi) {
    for (int i = lo+1; i <= hi; i++) {
        int j = i;
        Comparable t = a[j];
        while (j > lo && t.compareTo(a[j - 1]) < 0) {
            a[j] = a[j - 1];
            --j;
        }
        a[j] = t;
    }
} }
公共类并行合并排序{
私有静态最终ForkJoinPool线程池=新ForkJoinPool();
私有静态最终整数大小_阈值=16;
公共静态无效排序(可比[]a){
排序(a,0,a.length-1);
}
公共静态无效排序(可比[]a,整数低,整数高){
if(高-低<大小\阈值){
插入端口(a、lo、hi);
返回;
}
可比[]tmp=新的可比[a.长度];
调用(新的SortTask(a、tmp、lo、hi));
}
/**
*此类将替换以前使用的递归函数
*以前在这里。
*/
静态类SortTask扩展了RecursiveAction{
可比[]a;
可比[]tmp;
罗,你好,;
公共分拣任务(可比[]a,可比[]tmp,内部低,内部高){
这个a=a;
this.lo=lo;
hi=hi;
this.tmp=tmp;
}
@凌驾
受保护的void compute(){
if(高-低<大小\阈值){
插入端口(a、lo、hi);
返回;
}
int m=(低+高)/2;
//这两个递归调用将替换为对invokeAll的调用
invokeAll(新SortTask(a,tmp,lo,m),新SortTask(a,tmp,m+1,hi));
合并(a、tmp、lo、m、hi);
}
}
私有静态无效合并(可比[]a、可比[]b、整数lo、整数m、整数hi){

if(a[m].compareTo(a[m+1])很好的提示。但实际上我需要自己的实现。@ArtWorkAD。您可以使用框架自己实现它。我链接的文章只是想让您了解fork/join方面是如何工作的。@ArtWorkAD但是,为了自己学习实现,我添加了一个编辑。