我发布这个问题是因为我想向你们澄清在Java 1.7中使用F / J框架的概念,因为我看到互联网上的一些例子似乎没有意义。
使用List代替数组的代码是故意的。
这是递归合并排序的线性/常规版本。
package org.algorithms.sort;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class MergeSortor<T> {
private final List<T> items;
private final Comparator<T> c;
public MergeSortor(final List<T> original, final Comparator<T> c) {
if (original == null) {
this.items = Collections.emptyList();
} else {
this.items = original;
}
this.c = c;
}
protected List<T> compute() {
List<T> result = null;
int currentSize = this.items.size();
if (currentSize <= 1) {
result = items;
} else{
int midPoint = currentSize / 2;
List<T> left =new MergeSortor<T>(items.subList(0, midPoint), c).getSortedResult();
List<T> right =new MergeSortor<T>(items.subList(midPoint,
currentSize), c).getSortedResult();
result = merge(left,right);
}
return result;
}
private List<T> merge(List<T>left,List<T>right) {
List<T> result = new ArrayList<T>(left.size()+right.size());
T firstLeft = null;
T firstRight = null;
while (left.size() > 0 || right.size() > 0) {
if (left.size() > 0 && right.size() > 0) {
firstLeft = left.get(0);
firstRight = right.get(0);
if (c.compare(firstLeft, firstRight) <= 0) {
result.add(firstLeft);
left = left.subList(1, left.size());
} else {
result.add(firstRight);
right = right.subList(1, right.size());
}
} else if (left.size() > 0){
result.add(left.get(0));
left = left.subList(1, left.size());
} else if (right.size() > 0){
result.add(right.get(0));
right = right.subList(1, right.size());
}
}
return result;
}
public List<T> getSortedResult() {
return this.compute();
}
static public class IntegerComparator implements Comparator<Integer> {
@Override
public int compare(Integer o1, Integer o2) {
int f = o1.hashCode(); // Auto-unboxing
int s = o2.hashCode(); // Auto-unboxing
return f < s ? -1 : (f == s ? 0 : 1); // No unboxing
}
}
}
这是扩展The RecursiveTask的合并排序的F / J版本。
package org.algorithms.sort;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.RecursiveTask;
public class MergeTask<T> extends RecursiveTask<List<T>>{
private final List<T> items;
private final Comparator<T> c;
private static final long serialVersionUID = 8193108777395886772L;
public MergeTask(final List<T> original, final Comparator<T> c){
if (original == null) {
this.items = Collections.emptyList();
} else {
this.items = original;
}
this.c = c;
}
@Override
protected List<T> compute() {
List<T> result = null;
int currentSize = this.items.size();
if (currentSize <= 1) {
result = items;
} else{
int midPoint = currentSize / 2;
MergeTask<T> leftSortor = new MergeTask<T>(items.subList(0, midPoint), c);
MergeTask<T> rightSortor = new MergeTask<T>(items.subList(midPoint,
currentSize), c);
rightSortor.fork();
leftSortor.fork();
result = merge(leftSortor.join(),rightSortor.join());
}
return result;
}
private List<T> merge(List<T>left,List<T>right) {
List<T> result = new ArrayList<T>(left.size()+right.size());
T firstLeft = null;
T firstRight = null;
while (left.size() > 0 || right.size() > 0) {
if (left.size() > 0 && right.size() > 0) {
firstLeft = left.get(0);
firstRight = right.get(0);
if (c.compare(firstLeft, firstRight) <= 0) {
result.add(firstLeft);
left = left.subList(1, left.size());
} else {
result.add(firstRight);
right = right.subList(1, right.size());
}
} else if (left.size() > 0){
result.add(left.get(0));
left = left.subList(1, left.size());
} else if (right.size() > 0){
result.add(right.get(0));
right = right.subList(1, right.size());
}
}
return result;
}
}
这是调用它们的主程序。
package org.algorithms.sort;
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import org.algorithms.sort.MergeSortor.IntegerComparator;
public class SortingRunner {
public static void main(String[] args) throws InterruptedException, ExecutionException {
Integer[] initialOrders = new Integer[Short.MAX_VALUE*32];
Random random = new Random();
for (int i =0 ;i<Short.MAX_VALUE*32;i++){
initialOrders[i]=Integer.valueOf(random.nextInt(Integer.MAX_VALUE));
}
MergeSortor<Integer> sortor = new MergeSortor<Integer>(
Arrays.asList(initialOrders), new IntegerComparator());
ForkJoinPool pool = new ForkJoinPool();
MergeTask<Integer> task = new MergeTask<Integer>(Arrays.asList(initialOrders), new IntegerComparator());
long start = System.currentTimeMillis();
sortor.getSortedResult();
long end = System.currentTimeMillis();
System.out.println(end - start );
start = System.currentTimeMillis();
pool.invoke(task);
end = System.currentTimeMillis();
System.out.println(end - start );
}
}
我认为互联网上的问题是,大多数例子中的分叉是将分支任务的两条腿分开,或者先分叉左分叉部分然后向右分叉。
在使用F / J进行合并排序的情况下,我认为这应该是一个很大的不可以。
合并排序实际上是从左到右的线性依赖排序。首先分叉左边不会产生已经存在的任何进一步的并行过程。 F / J框架将fork()的所有内容按顺序提交到队列中,然后按提交顺序拾取并执行,由F / J池的每个工作线程分别执行。
然而,首先分叉将为您提供并行计算以后应该执行的内容(与原始/线性实现相比)的优势,并首先对尾部进行除法/合并。
让我知道你们的想法。并希望这将是使用F / J进行排序的一个很好的例子。