为什么我的多线程快速排序没有显示速度优势

时间:2016-04-21 15:27:01

标签: java multithreading algorithm sorting

所以这是我的代码:

/**
 * Created by TianTuoYou on 4/7/16.
 */
public class MTQuickSort implements SortingAlgorithm {

    private int threadAmount = 1;

    @Override
    public void sort(int[] list) {
        QuickSortRunnable quickSortRunnable = new QuickSortRunnable(list, 0, list.length - 1);
        quickSortRunnable.run();
    }

    private class QuickSortRunnable implements Runnable {

        private int[] list;
        private int low;
        private int high;

        public QuickSortRunnable(int[] list, int low, int high) {
            this.list = list;
            this.low = low;
            this.high = high;
        }

        @Override
        public void run() {
            quickSort(list, low, high);
        }

        private void quickSort(int[] list, int low, int high) {
            if (low < high) {
                int pivotLocation = partition(list, low, high);

                if (threadAmount < 5) {
                    Thread thread1 = new Thread(new QuickSortRunnable(list, low, pivotLocation - 1));
                    thread1.start();

                    Thread thread2 = new Thread(new QuickSortRunnable(list, pivotLocation + 1, high));
                    thread2.start();

                    threadAmount+=2;

                    try {
                        thread1.join();
                        thread2.join();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
                    quickSort(list, low, pivotLocation - 1);
                    quickSort(list, pivotLocation + 1, high);
                }
            }
        }

        private int partition(int[] list, int low, int high) {
            int pivot = list[high];
            int leftWall = low;

            int temp;
            for (int i = low; i < high; i ++) {
                if (list[i] <= pivot) {
                    leftWall ++;
                    temp = list[leftWall - 1];
                    list[leftWall - 1] = list[i];
                    list[i] = temp;
                }
            }

            temp = list[leftWall];
            list[leftWall] = list[high];
            list[high] = temp;

            return leftWall;
        }
    }
}

在我对此算法进行测试后,我发现无论输入多大,它都没有显示比单线程快速排序更快的速度,在大多数情况下它甚至更慢。任何人都可以解释原因吗?

1 个答案:

答案 0 :(得分:0)

在创建任何其他线程之前,

partition出现在主排序线程中。您partition的实现是O(N),这是分拣成本的主要部分,并且通过并行化其余部分可以消除任何实际收益。

partition之后,您创建了记录(N)个其他线程以在每个线程内重新分区数据,将O(N * log N)排序转换为O(N ^ log N) - 注意从乘以的权力的变化。请注意,您有一个竞争条件允许最多创建9个线程,尽管您最有可能看到使用5个或7个,其中9个非常罕见。

由于每个线程层都有效地重新排序整个列表,因此最终可能会执行至少O(N^5)个移动/比较操作。对于只需要排序的一百个元素,这可能需要2000万倍的实际快速排序操作。

请注意,无论您拥有多少内核,您都不可能超越内置的Java运行时排序 - 大多数Java运行时都是用C / C ++编写的,以避免像Java内存模型一样多的开销。可能。对于诸如整数的小块数组尤其如此。只要你有能力,就使用运行时排序。

如果您只是想出于教育目的而这样做,那么您将需要专注于并行化partition操作,并减少其中发生的掉期数量,因为这是您的大部分成本。