一、Fork-Join 簡介
fork/join 框架是 Java 7 中引入的 ,它是一個工具,通過 「 分而治之 」 的方法嘗試將所有可用的處理器內核使用起來幫助加速並行處理。在實際使用過程中,這種 「 分而治之 」的方法意味着框架首先要 fork
,遞歸地將任務分解爲較小的獨立子任務,直到它們足夠簡單以便異步執行。然後,join
部分開始工作,將所有子任務的結果遞歸地連接成單個結果,或者在返回 void 的任務的情況下,程序只是等待每個子任務執行完畢。
二、ForkJoinPool 線程池
ForkJoinPool
是 fork/join 框架的核心,是 ExecutorService
的一個實現,用於管理工作線程,並提供了一些工具來幫助獲取有關線程池狀態和性能的信息(工作竊取( work-stealing )算法)。
三、ForkJoinPool線程池的實例化
(1) 在Java8 中提供 commonPool() 靜態方法
ForkJoinPool commonPool = ForkJoinPool.commonPool();
(2) 在Java 7中 提供創建ForkJoinPool 的實例化方法
public static ForkJoinPool forkJoinPool = new ForkJoinPool(2);
四、ForkJoinTask 類
ForkJoinTask
是 ForkJoinPool
線程之中執行的任務的基本類型。我們日常使用時,一般不直接使用 ForkJoinTask
,而是擴展它的兩個子類中的任意一個:
1、任務不返回結果 ( 返回 void
) 的 RecursiveAction
2、返回值的任務的 RecursiveTask
這兩個類都有一個抽象方法 compute()
,用於定義任務的邏輯。
(1) RecursiveAction
類
public class CustomRecursiveAction extends RecursiveAction {
private String workload = "";
private static final int THRESHOLD = 4;
private static Logger logger =
Logger.getAnonymousLogger();
public CustomRecursiveAction(String workload) {
this.workload = workload;
}
@Override
protected void compute() {
if (workload.length() > THRESHOLD) {
ForkJoinTask.invokeAll(createSubtasks());
} else {
processing(workload);
}
}
private List<CustomRecursiveAction> createSubtasks() {
List<CustomRecursiveAction> subtasks = new ArrayList<>();
String partOne = workload.substring(0, workload.length() / 2);
String partTwo = workload.substring(workload.length() / 2, workload.length());
subtasks.add(new CustomRecursiveAction(partOne));
subtasks.add(new CustomRecursiveAction(partTwo));
return subtasks;
}
private void processing(String work) {
String result = work.toUpperCase();
logger.info("This result - (" + result + ") - was processed by "
+ Thread.currentThread().getName());
}
}
(2) RecursiveTask 類
對於有返回值的任務,除了將每個子任務的結果在一個結果中合併,其它邏輯和 RecursiveAction
都差不多。
public class CustomRecursiveTask extends RecursiveTask<Integer> {
private int[] arr;
private static final int THRESHOLD = 20;
public CustomRecursiveTask(int[] arr) {
this.arr = arr;
}
@Override
protected Integer compute() {
if (arr.length > THRESHOLD) {
return ForkJoinTask.invokeAll(createSubtasks())
.stream()
.mapToInt(ForkJoinTask::join)
.sum();
} else {
return processing(arr);
}
}
private Collection<CustomRecursiveTask> createSubtasks() {
List<CustomRecursiveTask> dividedTasks = new ArrayList<>();
dividedTasks.add(new CustomRecursiveTask(
Arrays.copyOfRange(arr, 0, arr.length / 2)));
dividedTasks.add(new CustomRecursiveTask(
Arrays.copyOfRange(arr, arr.length / 2, arr.length)));
return dividedTasks;
}
private Integer processing(int[] arr) {
return Arrays.stream(arr)
.filter(a -> a > 10 && a < 27)
.map(a -> a * 10)
.sum();
}
}
五、 將任務提交到 ForkJoinPool 線程池中
(1) submit() 方法
forkJoinPool.submit(customRecursiveTask);
int result = customRecursiveTask.join();
(2) execute 方法
forkJoinPool.execute(customRecursiveTask);
int result = customRecursiveTask.join();
(3) 使用 invoke()
或 invokeAll( ) 方法 fork
任務並等待結果,不需要任何手動連接 ( join )
int result = forkJoinPool.invoke(customRecursiveTask);
當涉及到多個任務且要保證任務的順序時,通常都是使用 ForkJoinPool.invokeAll()
(4)最終執行程序
package day01;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveAction;
import java.util.logging.Logger;
/**
* fork-Join方法實現
* @author zc
*
*/
public class ForkJoinTest extends RecursiveAction {
private static final long serialVersionUID = 1L;
private String workload = "";
private static final int THRESHOLD = 4;
private static Logger logger =
Logger.getAnonymousLogger();
public ForkJoinTest(String workload) {
this.workload = workload;
}
@Override
protected void compute() {
if (workload.length() > THRESHOLD) {
ForkJoinTask.invokeAll(createSubtasks());
}else {
processing(workload);
}
}
private List<ForkJoinTest> createSubtasks() {
List<ForkJoinTest> subtasks = new ArrayList<>();
String partOne = workload.substring(0, workload.length() / 2);
String partTwo = workload.substring(workload.length() / 2, workload.length());
subtasks.add(new ForkJoinTest(partOne));
subtasks.add(new ForkJoinTest(partTwo));
return subtasks;
}
private void processing(String work) {
String result = work.toUpperCase();
logger.info("This result - (" + result + ") - was processed by "
+ Thread.currentThread().getName());
}
public static void main(String[] args) {
// (1) ForkJoinPool實例化方式一
ForkJoinPool commonPool =ForkJoinPool.commonPool();
// (2) ForkJoinPool實例化方式二, 2代表兩個處理單元
ForkJoinPool forkJoinPool =new ForkJoinPool(2);
ForkJoinTest forkJoin = new ForkJoinTest("tewrerefedewrewr");
commonPool.submit(forkJoin);
//執行計算結果
forkJoin.join();
}
}