多线程数组排序Java

时间:2011-12-23 07:06:30

标签: java arrays sorting

你好!

我正在尝试使用多个线程对int数组进行排序。现在我有这样的事情:

import java.util.Arrays;


public class MultiTread extends  Thread{

int sizeOfArray;
public static int treadsN = 4;
public  static  int sortFrom;
public  static  int sortTo;

public MultiTread(int sizeOfArray, int treadsN) {
    this.sizeOfArray = sizeOfArray;
    this.treadsN = treadsN;
}

public MultiTread(int[] arrayToSort, int sizeOfArray) {
    this.sizeOfArray = sizeOfArray;
}



public static int [] creatingArray(int sizeOfArray) {
    int [] arrayToSort = new int[sizeOfArray];
    int arrayLength = arrayToSort.length;
    for (int counter = 0; counter<arrayLength; counter++){
        arrayToSort[counter] = (int)(8000000*Math.random());
    }
    return arrayToSort;
}

public  static  int [] sortInSeveralTreads(final int [] arrayToSort){
    int [] newArr = new int[arrayToSort.length];
    int numberOfThreads = treadsN;
    if (numberOfThreads == 0){
        System.out.println("Incorrect value");
        return arrayToSort;
    }
    if (numberOfThreads == 1){
        Arrays.sort(arrayToSort);
        System.out.println("Array sorted in 1 thread");
    } else {
         final int lengthOfSmallArray = arrayToSort.length/numberOfThreads;
        sortFrom = 0;
        sortTo = lengthOfSmallArray;
        for (int progress = 0; progress < numberOfThreads; progress++){
            final int [] tempArr = Arrays.copyOfRange(arrayToSort,sortFrom,sortTo);
            new Thread(){public void run() {
                Arrays.sort(tempArr);
            }}.start();
            sortFrom = sortTo;
            sortTo += lengthOfSmallArray;
            newArr =  mergeSort(newArr, tempArr);
        }
        new Thread(){public void run() {
            Arrays.sort(Arrays.copyOfRange(arrayToSort, arrayToSort.length-lengthOfSmallArray, arrayToSort.length));
        }}.start();
        newArr = mergeSort(newArr, arrayToSort);
    }
    return newArr;
}

public static  int [] mergeSort(int [] arrayFirst, int [] arraySecond){
    int [] outputArray = new  int[arrayFirst.length+arraySecond.length];
    while (arrayFirst.length != 0 && arraySecond.length != 0){
        int counter = 0;
        if (arrayFirst[0] < arraySecond[0]){
            outputArray[counter] = arrayFirst[0];
            counter++;
            arrayFirst = Arrays.copyOfRange(arrayFirst, 1, arrayFirst.length);
        }else {
            outputArray[counter] = arraySecond[0];
            counter++;
            arraySecond = Arrays.copyOfRange(arraySecond, 1, arraySecond.length);
        }
    }
    return outputArray;
}


public static void main(String[] args){
    long startTime;
    long endTime;
    int [] a = creatingArray(8000000);
    startTime = System.currentTimeMillis();
    a =  sortInSeveralTreads(a);
    endTime = System.currentTimeMillis();
    System.out.println(Thread.activeCount());
    System.out.printf("Sorted by: %d treads in %.7f seconds %n", treadsN, (float)(endTime-startTime)*1e-6);
    try {
        Thread.currentThread().sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println(Thread.activeCount());
}
}

我知道这不是很好的实现。所有工作正常但合并排序工作太糟糕 - 它崩溃...错误应该在那行:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOfRange(Arrays.java:3137)
at MultiTread.mergeSort(MultiTread.java:78)
at MultiTread.sortInSeveralTreads(MultiTread.java:61)
at MultiTread.main(MultiTread.java:94)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

我做错了什么?

3 个答案:

答案 0 :(得分:1)

好吧,你已经没有使用J.V.M允许的内存了。

我没有检查过你的算法是否正确,但是你应该尝试使用更小的数组来查看代码是否正常,比如说1000。

在整个程序中,在线程中制作数组的副本(或至少部分副本)。然后每个线程分配大量数据。因此,您可能希望重新考虑您的设计,否则您将继续遇到此问题。如果你发现无法减少这种分配并且我的下一段对你没用,那么你可能需要使用文件来对这些大型数组进行排序,而不是试图一次性将所有内容保存在内存中。

您可以按照此页面上的说明增加堆大小(我找到的第一个链接,但它有正确的信息): http://viralpatel.net/blogs/2009/01/jvm-java-increase-heap-size-setting-heap-size-jvm-heap.html 这将允许您从Java程序中保留分配更多内存。

答案 1 :(得分:1)

好的,有几个问题:

首先,您的数组大小太大了。这就是为什么你的内存耗尽(8000000)应该尝试使用低数字1000.即使这样你的代码可能会崩溃到其他地方。

第二,你的代码没有多大意义,因为你正在混合静态和非静态调用... Thread.currentThread().sleep(1000)很奇怪,你不在当前的线程中。

执行Array.sort的线程创建。

我建议首先在处理排序作业之前创建一个简单的多线程程序。还建议您实现Runnable接口,而不是扩展Thread类以创建工作类。

答案 2 :(得分:0)

while (arrayFirst.length != 0 && arraySecond.length != 0){

在符合infinite后,loop conditions就会进入memory heapOutOfMemoryError正在terminated

它根本不是terminate所以你应该在{{1}}这个循环中包含一些代码。