你好!
我正在尝试使用多个线程对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)
我做错了什么?
答案 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 heap
,OutOfMemoryError
正在terminated
它根本不是terminate
所以你应该在{{1}}这个循环中包含一些代码。