我正在阅读Java ForkJoin框架。在ForkJoinTask
(例如RecursiveTask
)的实施中,如果不直接呼叫invoke()
还有什么额外的好处,但是要实例化ForkJoinPool
并呼叫pool.invoke(task)
?当我们将这两种方法称为invoke
时究竟发生了什么?ForkJoinPool.invoke()和ForkJoinTask.invoke()或compute()
从源头上看,如果recursiveTask.invoke
被调用,它将调用它的exec
并最终以管理的线程池方式调用compute
。因此,为什么我们有成语pool.invoke(task)
更令人困惑。
我写了一些简单的代码来测试性能差异,但我没有看到任何。也许测试代码是错误的?请看下图:
public class MyForkJoinTask extends RecursiveAction {
private static int totalWorkInMillis = 20000;
protected static int sThreshold = 1000;
private int workInMillis;
public MyForkJoinTask(int work) {
this.workInMillis = work;
}
// Average pixels from source, write results into destination.
protected void computeDirectly() {
try {
ForkJoinTask<Object> objectForkJoinTask = new ForkJoinTask<>();
Thread.sleep(workInMillis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
protected void compute() {
if (workInMillis < sThreshold) {
computeDirectly();
return;
}
int discountedWork = (int) (workInMillis * 0.9);
int split = discountedWork/2;
invokeAll(new MyForkJoinTask(split),
new MyForkJoinTask(split));
}
public static void main(String[] args) throws Exception {
System.out.printf("Total work is %d in millis.%n", totalWorkInMillis);
System.out.printf("Threshold is %d in millis.%n", sThreshold);
int processors = Runtime.getRuntime().availableProcessors();
System.out.println(Integer.toString(processors) + " processor"
+ (processors != 1 ? "s are " : " is ")
+ "available");
MyForkJoinTask fb = new MyForkJoinTask(totalWorkInMillis);
ForkJoinPool pool = new ForkJoinPool();
long startTime = System.currentTimeMillis();
// These 2 seems no difference!
pool.invoke(fb);
// fb.compute();
long endTime = System.currentTimeMillis();
System.out.println("Took " + (endTime - startTime) +
" milliseconds.");
}
}
感谢您的回答。但'RecursiveTask'也有一个继承的'invoke'方法,通常在其主'compute'方法内调用'invoke'。那是什么呢?还有,怎么没有性能差异? – Boyang
所以我深入了解源代码。如果调用'recursiveTask.invoke',它将以托管线程池的方式调用它的'exec'并最终'compute'。在这种情况下,我更加困惑于成语'pool.invoke(task)'。为什么? – Boyang
请参阅我的新的编辑 – Boyang