【JDK7】新特性(5) fork/join 框架

    對於框架的原理,能夠閱讀 Doug Lea 的文章「A Java Fork/Join Framework」:瞭解 Fork/Join 模式的實現機制和執行性能。
    原理解析:fork分解,join結合。這個框架的本質是將一個任務分解成多個子任務,每一個子任務用單獨的線程去處理。這裏用到了遞歸的思想。框架的結構圖能夠參考 html



 圖片來源(http://www.ibm.com/developerworks/cn/java/j-lo-forkjoin/index.htmljava

    使用fork/join 框架很簡單,
        1.實現子問題的通常求解算法
        2.如何分解問題
        3.繼承 RecursiveAction ,實現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的使用。(後面才發現,選用這個案例是很是失敗的,由於二分查找的時間是logn,而建立線程的開銷更大,這樣並不能體現多線程二分查找的優點,因此這個代碼不具備實用性,只是爲了說明如何使用框架:)
    代碼以下:
BinarySearchProblem.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
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);  
       }  
    }  
      
    //構造數據  
    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 還能夠帶返回值,這裏給出一段代碼做爲參考(斐波那契函數)

(來自http://www.ibm.com/developerworks/cn/java/j-lo-forkjoin/index.html框架

class Fibonacci extends RecursiveTask<Integer> {  
    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();  
    }  
}

    只要問題可以分解成相似子問題的,均可以使用這個框架。對於大批量的數據尤爲合適 異步

【JDK7】新特性(1)概述:http://my.oschina.net/zhengjian/blog/94467
【JDK7】新特性(2)語法:http://my.oschina.net/zhengjian/blog/94473
【JDK7】新特性(3)JDBC4.1:http://my.oschina.net/zhengjian/blog/95070
【JDK7】新特性(4)NIO2.0 文件系統:http://my.oschina.net/zhengjian/blog/95071
【JDK7】新特性(5)fork/join 框架:http://my.oschina.net/zhengjian/blog/95072
【JDK7】新特性(6)監聽文件系統的更改:http://my.oschina.net/zhengjian/blog/95077
【JDK7】新特性(7)監聽文件系統的更改:http://my.oschina.net/zhengjian/blog/95078
【JDK7】新特性(8)異步io/AIO:http://my.oschina.net/zhengjian/blog/95081

原文地址: http://janeky.iteye.com/blog/1047805
相關文章
相關標籤/搜索