Java 将ExecutorService与多线程版本的合并排序一起使用
我正在做一个家庭作业,我必须创建一个多线程版本的合并排序。我能够实现它,但我无法停止线程的创建。我曾研究过使用ExecutorService来限制线程的创建,但我不知道如何在当前代码中实现它 这是我当前的多线程合并排序。我们需要实现一个特定的策略模式,这就是我的Java 将ExecutorService与多线程版本的合并排序一起使用,java,multithreading,algorithm,Java,Multithreading,Algorithm,我正在做一个家庭作业,我必须创建一个多线程版本的合并排序。我能够实现它,但我无法停止线程的创建。我曾研究过使用ExecutorService来限制线程的创建,但我不知道如何在当前代码中实现它 这是我当前的多线程合并排序。我们需要实现一个特定的策略模式,这就是我的sort()方法的来源 @Override public int[] sort(int[] list) { int array_size = list.length; list = msort(list, 0, array
sort()
方法的来源
@Override
public int[] sort(int[] list) {
int array_size = list.length;
list = msort(list, 0, array_size-1);
return list;
}
int[] msort(int numbers[], int left, int right) {
final int mid;
final int leftRef = left;
final int rightRef = right;
final int array[] = numbers;
if (left<right) {
mid = (right + left) / 2;
//new thread
Runnable r1 = new Runnable(){
public void run(){
msort(array, leftRef, mid);
}
};
Thread t1 = new Thread(r1);
t1.start();
//new thread
Runnable r2 = new Runnable(){
public void run(){
msort(array, mid+1, rightRef);
}
};
Thread t2 = new Thread(r2);
t2.start();
//join threads back together
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
merge(numbers, leftRef, mid, mid+1, rightRef);
}
return numbers;
}
void merge(int numbers[], int startA, int endA, int startB, int endB) {
int finalStart = startA;
int finalEnd = endB;
int indexC = 0;
int[] listC = new int[numbers.length];
while(startA <= endA && startB <= endB){
if(numbers[startA] < numbers[startB]){
listC[indexC] = numbers[startA];
startA = startA+1;
}
else{
listC[indexC] = numbers[startB];
startB = startB +1;
}
indexC++;
}
if(startA <= endA){
for(int i = startA; i < endA; i++){
listC[indexC]= numbers[i];
indexC++;
}
}
indexC = 0;
for(int i = finalStart; i <= finalEnd; i++){
numbers[i]=listC[indexC];
indexC++;
}
}
@覆盖
公共int[]排序(int[]列表){
int array_size=list.length;
列表=msort(列表,0,数组大小-1);
退货清单;
}
int[]msort(int编号[],int左,int右){
最终int mid;
final int leftRef=左;
最终int righref=右;
最终整数数组[]=数字;
如果(左正如mcdowella所指出的,Java7中的Fork/Join框架正是针对可以递归地分解成更小部分的任务
实际上,的Javadoc有一个合并排序作为第一个示例:)
还请注意,这是一个ExecutorService。在@mcdowella的评论之后,我还认为如果您想限制并行运行的线程数量,fork/join框架是您的最佳选择
我知道这对你的家庭作业没有任何帮助,因为你可能不被允许使用Java7中的fork/join框架。但是它即将学到一些东西,不是吗?;)
正如我所评论的,我认为您的合并方法是错误的。我无法确定失败的原因,但我已经重写了它。我强烈建议您编写一个包含合并方法期间可能发生的所有边缘情况的测试用例,如果您验证了它的有效性,请将它移植回您的多线程代码中
@lbalazscs还提示您,javadocs中提到了fork/join排序,但是我没有其他事情要做——因此,如果您使用Java7实现它,我将向您展示解决方案
public class MultithreadedMergeSort extends RecursiveAction {
private final int[] array;
private final int begin;
private final int end;
public MultithreadedMergeSort(int[] array, int begin, int end) {
this.array = array;
this.begin = begin;
this.end = end;
}
@Override
protected void compute() {
if (end - begin < 2) {
// swap if we only have two elements
if (array[begin] > array[end]) {
int tmp = array[end];
array[end] = array[begin];
array[begin] = tmp;
}
} else {
// overflow safe method to calculate the mid
int mid = (begin + end) >>> 1;
// invoke recursive sorting action
invokeAll(new MultithreadedMergeSort(array, begin, mid),
new MultithreadedMergeSort(array, mid + 1, end));
// merge both sides
merge(array, begin, mid, end);
}
}
void merge(int[] numbers, int startA, int startB, int endB) {
int[] toReturn = new int[endB - startA + 1];
int i = 0, k = startA, j = startB + 1;
while (i < toReturn.length) {
if (numbers[k] < numbers[j]) {
toReturn[i] = numbers[k];
k++;
} else {
toReturn[i] = numbers[j];
j++;
}
i++;
// if we hit the limit of an array, copy the rest
if (j > endB) {
System.arraycopy(numbers, k, toReturn, i, startB - k + 1);
break;
}
if (k > startB) {
System.arraycopy(numbers, j, toReturn, i, endB - j + 1);
break;
}
}
System.arraycopy(toReturn, 0, numbers, startA, toReturn.length);
}
public static void main(String[] args) {
int[] toSort = { 55, 1, 12, 2, 25, 55, 56, 77 };
ForkJoinPool pool = new ForkJoinPool();
pool.invoke(new MultithreadedMergeSort(toSort, 0, toSort.length - 1));
System.out.println(Arrays.toString(toSort));
}
根据它的javadoc:
创建并行度等于的ForkJoinPool
java.lang.Runtime.AvailableProcessor,使用默认线程
工厂、无UncaughtExceptionHandler和非异步后进先出处理
模式
还要注意我的合并方法与你的不同,因为我认为这是你的主要问题。如果我用我的合并方法替换你的合并方法,至少你的排序是有效的。只需在你的msort()中设置某种“计数”:“ExecutorService()”如果我错了,请纠正我,但在我看来,如果您限制当前设计的线程数量,代码将永远无法完成。您需要来自“底层”线程的结果,以便join()
将在下一个“层”返回。我建议您查找有关ForkJoinTask的文章,该文章仅适用于这类内容-例如,当您有大量数据要排序时,您只想创建一个新线程,例如10+K。创建一个线程的成本远低于此值可能会比收益更高。您只需创建e一个线程而不是两个线程,因为您已经有一个正在运行的线程。顺便说一句,您可能希望将线程数限制为您拥有的CPU数。您的合并方法在我看来非常错误和浪费。感谢您提供Java7多线程合并排序,它排序速度比我的快得多,令人难以置信。我能够使用您的合并方法纠正我的错误。
ForkJoinPool pool = new ForkJoinPool();