簡體   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