我正在閱讀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