繁体   English   中英

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

[英]Realize worker-threads for merge sort algorithm

我有一个单线程版本的合并排序http://pastebin.com/2uMGjTxr

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

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

    return mergeSort(array, 0, array.length);
}

现在我想在java中使用多线程技术来提高性能。 代码来自我的导师,他说我必须在sort方法中添加一些东西但实际上让我感到困惑。

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

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

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

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

您可以下载JSR 166二进制文件 有关更多信息, 是一篇很好的文章

编辑以解决您的评论:

如果你想自己实现它,你不希望每个子列表都有一个新的Thread。 您可以想象,将对给定数组中的许多分区进行排序,以使每个分区的线程变得更大(假设数组足够大)。 相反,您需要为每个分区数组创建一个线程,您将实际进行合并工作。 ForkJoin为您完成此任务,使用FJ池的一个好处是它将重用线程而不是为子流程合并创建新线程。

在java 7中使用RecursiveAction

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM