使用新的 Fork/join 框架相对于在开始时简单地将大任务分割成 N 个子任务,将它们发送到一个缓存的线程池(来自 执行者)并等待每个任务完成,有什么好处呢?我没有看到使用 fork/join 抽象是如何简化问题的,或者是如何使解决方案比多年前更有效率的。
例如,教程示例中的并行模糊算法可以这样实现:
public class Blur implements Runnable {
private int[] mSource;
private int mStart;
private int mLength;
private int[] mDestination;
private int mBlurWidth = 15; // Processing window size, should be odd.
public ForkBlur(int[] src, int start, int length, int[] dst) {
mSource = src;
mStart = start;
mLength = length;
mDestination = dst;
}
public void run() {
computeDirectly();
}
protected void computeDirectly() {
// As in the example, omitted for brevity
}
}
在开始时拆分并将任务发送到线程池:
// source image pixels are in src
// destination image pixels are in dst
// threadPool is a (cached) thread pool
int maxSize = 100000; // analogous to F-J's "sThreshold"
List<Future> futures = new ArrayList<Future>();
// Send stuff to thread pool:
for (int i = 0; i < src.length; i+= maxSize) {
int size = Math.min(maxSize, src.length - i);
ForkBlur task = new ForkBlur(src, i, size, dst);
Future f = threadPool.submit(task);
futures.add(f);
}
// Wait for all sent tasks to complete:
for (Future future : futures) {
future.get();
}
// Done!
这些任务进入线程池的队列,在工作线程可用时从队列执行这些任务。只要拆分的粒度足够大(以避免特别等待最后一个任务) ,并且线程池有足够多的线程(至少有 N 个处理器) ,所有处理器都会全速运行,直到完成整个计算。
我是否遗漏了什么? 使用 fork/join 框架的附加值是什么?