探秘JDK7新特性之fork/join框架
原理解析:fork分解,join結合。這個框架的本質是將一個任務分解成多個子任務,每個子任務用單獨的線程去處理。這里用到了遞歸的思想??蚣艿慕Y構圖可以參考

圖片來源(http://www.ibm.com/developerworks/cn/java/j-lo-forkjoin/index.html)
使用fork/join 框架很簡單,
1.實現(xiàn)子問題的一般求解算法
2.如何分解問題
3.繼承 RecursiveAction ,實現(xiàn)compute()方法
偽代碼代碼
- Result solve(Problem problem) {
- if (problem is small)
- directly solve problem
- else {
- split problem into independent parts
- fork new subtasks to solve each part
- join all subtasks
- compose result from subresults
- }
這里我通過一個改進的二分查找來講解fork/join的使用。(后面才發(fā)現(xiàn),選用這個案例是非常失敗的,因為二分查找的時間是logn,而創(chuàng)建線程的開銷更大,這樣并不能體現(xiàn)多線程二分查找的優(yōu)勢,所以這個代碼不具有實用性,只是為了說明如何使用框架:)
代碼如下:
BinarySearchProblem.java
Java代碼
- package testjdk7;
- import java.util.Arrays;
- /**
- * @author kencs@foxmail.com
- */
- public class BinarySearchProblem {
- private final int[] numbers;
- private final int start;
- private final int end;
- public final int size;
- public BinarySearchProblem(int[] numbers,int start,int end){
- this.numbers = numbers;
- this.start = start;
- this.end = end;
- this.size = end -start;
- }
- public int searchSequentially(int numberToSearch){
- //偷懶,不自己寫二分查找了
- return Arrays.binarySearch(numbers, start, end, numberToSearch);
- }
- public BinarySearchProblem subProblem(int subStart,int subEnd){
- return new BinarySearchProblem(numbers,start+subStart,start+subEnd);
- }
- }
BiSearchWithForkJoin.java
Java代碼
- package testjdk7;
- import java.util.concurrent.ForkJoinPool;
- import java.util.concurrent.RecursiveAction;
- /**
- * @author kencs@foxmail.com
- */
- public class BiSearchWithForkJoin extends RecursiveAction {
- private final int threshold;
- private final BinarySearchProblem problem;
- public int result;
- private final int numberToSearch;
- public BiSearchWithForkJoin(BinarySearchProblem problem,int threshold,int numberToSearch){
- this.problem = problem;
- this.threshold = threshold;
- this.numberToSearch = numberToSearch;
- }
- @Override
- protected void compute() {
- if(problem.size < threshold){ //小于閥值,就直接用普通的二分查找
- result = problem.searchSequentially(numberToSearch);
- }else{
- //分解子任務
- int midPoint = problem.size/2;
- BiSearchWithForkJoin left = new BiSearchWithForkJoin(problem.subProblem(0, midPoint),threshold,numberToSearch);
- BiSearchWithForkJoin right = new BiSearchWithForkJoin(problem.subProblem(midPoint+1, problem.size),threshold,numberToSearch);
- invokeAll(left,right);
- result = Math.max(left.result, right.result);
- }
- }
- //構造數(shù)據(jù)
- private static final int[] data = new int[1000_0000];
- static{
- for(int i = 0;i<1000_0000;i++){
- data[i] = i;
- }
- }
- public static void main(String[] args){
- BinarySearchProblem problem = new BinarySearchProblem(data,0,data.length);
- int threshold = 100;
- int nThreads = 10;
- //查找100_0000所在的下標
- BiSearchWithForkJoin bswfj = new BiSearchWithForkJoin(problem,threshold,100_0000);
- ForkJoinPool fjPool = new ForkJoinPool(nThreads);
- fjPool.invoke(bswfj);
- System.out.printf("Result is:%d%n",bswfj.result);
- }
- }
RecursiveTask 還可以帶返回值,這里給出一段代碼作為參考(斐波那契函數(shù))
(來自http://www.ibm.com/developerworks/cn/java/j-lo-forkjoin/index.html)
Java代碼
- class Fibonacci extends RecursiveTask
{ - final int n;
- Fibonacci(int n) {
- this.n = n;
- }
- private int compute(int small) {
- final int[] results = { 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 };
- return results[small];
- }
- public Integer compute() {
- if (n <= 10) {
- return compute(n);
- }
- Fibonacci f1 = new Fibonacci(n - 1);
- Fibonacci f2 = new Fibonacci(n - 2);
- System.out.println("fork new thread for " + (n - 1));
- f1.fork();
- System.out.println("fork new thread for " + (n - 2));
- f2.fork();
- return f1.join() + f2.join();
- }
- }
用途
只要問題能夠分解成類似子問題的,都可以使用這個框架。對于大批量的數(shù)據(jù)尤其合適
參考資料
Jdk7官網(wǎng) http://openjdk.java.net/projects/jdk7/
(注:這篇文章發(fā)表時,JDK7未正式公布,可能有誤差,具體以官方正式版為準)
【編輯推薦】