繁体   English   中英

使用多线程进行合并排序

[英]Merge-sort using Multi-threading

我尝试使用多线程并行化合并排序,这是我的代码(如果执行不当,请原谅,我不在乎程序的空间复杂性)。 我正在实现排序数组。我的问题是:此过程是否会真正减少对大型数组进行排序所需的时间?需要进行哪些修改才能使其高效使用?

import java.io.IOException;
import java.util.Arrays;
import java.util.Random;
import java.util.Scanner;

public class Merge {
    public static int[] inputArray;
    public static int[] arr1;
    public static int[] arr2;
    public static int[] arr3;
    public static int t1_status=0;
    public static int t2_status=0;

    public static void main(String[] args) throws IOException{

        System.out.println("Enter the length of the array");

        Scanner in =new Scanner(System.in);

        int arraySize=in.nextInt();

        inputArray = new int[arraySize];

        Random rand=new Random();

        for(int i=0;i<arraySize;i++)
        {
            inputArray[i]=rand.nextInt(100);
        }

        //diving the original array into two subarrays

        arr1=Arrays.copyOfRange(inputArray, 0, inputArray.length/2);

        arr2=Arrays.copyOfRange(inputArray, (inputArray.length)/2,inputArray.length);
        //printing the original array
        System.out.print("The original array is array is ");

        for(int h:inputArray)
        {
            System.out.println(h);
        }

        Thread t1=new Thread(new Runnable(){
                public void run() 
                {
                    mergeSort(arr1);
                    System.out.println("t1 started");
                }

            });
        Thread t2=new Thread(new Runnable(){
                public void run()
                {
                    mergeSort(arr2);
                    System.out.println("t2 started");
                }

            });
        //starting threads
        t1.start();
        t2.start();

        try {
            t1.join();
            t2.join();
        }
        catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        if(t1.isAlive())
        {
            t1_status=1;
        }
        if(t2.isAlive())
        {
            t2_status=1;
        }
        t1.stop();
        t2.stop();

        arr3=new int[inputArray.length];

        merge(arr3,arr1,arr2);//merging arr1 and arr2.At this point both arr1 and arr2 are sorted.

        System.out.println("The sorted array is ");
        for(int m:arr3)
        {
            System.out.print(m);
            System.out.print(" ");
        }
        System.out.println(" ");
    }

    static void mergeSort(int[] A)
    {
        if (A.length > 1) 
        {
            int q = A.length/2;

            int[] leftArray = Arrays.copyOfRange(A, 0, q);
            int[] rightArray = Arrays.copyOfRange(A,q,A.length);
            mergeSort(leftArray);
            mergeSort(rightArray);
            merge(A,leftArray,rightArray);
        }
    }
    //merge function

    static void merge(int[] a, int[] l, int[] r) {
        int totElem = l.length + r.length;

        int i,li,ri;
        i = li = ri = 0;
        while ( i < totElem) {
            if ((li < l.length) && (ri<r.length)) {
                if (l[li] < r[ri]) {
                    a[i] = l[li];
                    i++;
                    li++;
                }
                else {
                    a[i] = r[ri];
                    i++;
                    ri++;
                }
            }
            else {
                if (li >= l.length) {
                    while (ri < r.length) {
                        a[i] = r[ri];
                        i++;
                        ri++;
                    }
                }
                if (ri >= r.length) {
                    while (li < l.length) {
                        a[i] = l[li];
                        li++;
                        i++;
                    }
                }
            }
        }

        if(t1_status==1){arr1=a;}
        else if(t2_status==1){arr2=a;}
        else{arr3=a;}
    }
}

是的,它可以提供帮助,这在很大程度上取决于您拥有多少个内核以及阵列的大小。 生成线程和协调工作不是免费的。 关于实际上有多少个并行线程有用的地方很柔和。

我认为您做的太少了,但是这很容易过大:由于该进程受CPU限制,因此每个核心都需要一个线程。

固定线程池/执行器在这里很方便。

CSE373上查看一些性能提升的示例:数据结构和算法/ MergeSort

将两个半部分分别放在单独的线程中是一个不错的开始,但是您也可以通过合并利用并行性。

另外,您也应该并行地并行执行子分类……但是要跟踪递归的深度,并在已经使用完所有内核时停止创建新线程。 为这些微小的小叶排序创建新线程是巨大的开销。

全部一起:

  1. 分为2个线程
  2. 首先,线程1对源数组的前半部分进行排序,线程2对源数组的后半部分进行排序。 为了对富人进行排序,他们可以递归调用此函数,或者如果2 ^ recursion_depth> number_of_cores则切换为串行排序; 然后
  3. 线程1将两个半部分都向前合并到目标的前半部分,线程2将两个半部分都向后合并到目标的后半部分。 当它们到达目的地的中点时,它们都停止。

请参见Collections.parallelSort()和Fork / Join框架javadoc。

足够小的数组在单线程上按旧排序,但是当足够大时(我认为是8192),parallelSort将使用ForkJoinPool默认池(与内核数量一样多的线程)进行分而治之。

仅使用2个线程可能会使速度加倍,但不会更多。

仅供参考,启动器线程也应该起作用,而不仅仅是坐在那里加入。 例如,它可以采用第二线程的工作。 然后只加入一次。

暂无
暂无

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

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