[英]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 。
将两个半部分分别放在单独的线程中是一个不错的开始,但是您也可以通过合并利用并行性。
另外,您也应该并行地并行执行子分类……但是要跟踪递归的深度,并在已经使用完所有内核时停止创建新线程。 为这些微小的小叶排序创建新线程是巨大的开销。
全部一起:
请参见Collections.parallelSort()和Fork / Join框架javadoc。
足够小的数组在单线程上按旧排序,但是当足够大时(我认为是8192),parallelSort将使用ForkJoinPool默认池(与内核数量一样多的线程)进行分而治之。
仅使用2个线程可能会使速度加倍,但不会更多。
仅供参考,启动器线程也应该起作用,而不仅仅是坐在那里加入。 例如,它可以采用第二线程的工作。 然后只加入一次。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.