JDK7新特性<五> fork/join 框架

对于框架的原理,可以阅读 Doug Lea 的文章“A Java Fork/Join Framework”:了解 Fork/Join 模式的实现机制和执行性能。

 

 

原理解析:fork分解,join结合。这个框架的本质是将一个任务分解成多个子任务,每个子任务用单独的线程去处理。这里用到了递归的思想。框架的结构图可以参考



 图片来源(http://www.ibm.com/developerworks/cn/java/j-lo-forkjoin/index.html

 

 

使用fork/join 框架很简单,

1.实现子问题的一般求解算法

2.如何分解问题

3.继承 RecursiveAction ,实现compute()方法

 

伪代码代码   收藏代码
  1.      Result solve(Problem problem) {  
  2. if (problem is small)  
  3.     directly solve problem  
  4. else {  
  5.     split problem into independent parts  
  6.     fork new subtasks to solve each part  
  7.     join all subtasks  
  8.     compose result from subresults  
  9. }  
 

 

 

这里我通过一个改进的二分查找来讲解fork/join的使用。(后面才发现,选用这个案例是非常失败的,因为二分查找的时间是logn,而创建线程的开销更大,这样并不能体现多线程二分查找的优势,所以这个代码不具有实用性,只是为了说明如何使用框架:)

 

代码如下:

BinarySearchProblem.java

 

 

Java代码   收藏代码
  1. package testjdk7;  
  2.   
  3. import java.util.Arrays;  
  4. /** 
  5.  * @author kencs@foxmail.com 
  6.  */  
  7. public class BinarySearchProblem {  
  8.     private final int[] numbers;  
  9.     private final int start;  
  10.     private final int end;  
  11.     public final int size;  
  12.       
  13.     public BinarySearchProblem(int[] numbers,int start,int end){  
  14.         this.numbers = numbers;  
  15.         this.start = start;  
  16.         this.end = end;  
  17.         this.size = end -start;  
  18.     }  
  19.       
  20.     public int searchSequentially(int numberToSearch){  
  21.        //偷懒,不自己写二分查找了  
  22.        return Arrays.binarySearch(numbers, start, end, numberToSearch);  
  23.     }  
  24.       
  25.     public BinarySearchProblem subProblem(int subStart,int subEnd){  
  26.         return new BinarySearchProblem(numbers,start+subStart,start+subEnd);  
  27.     }  
  28. }  

 

 BiSearchWithForkJoin.java

 

Java代码   收藏代码
  1. package testjdk7;  
  2. import java.util.concurrent.ForkJoinPool;  
  3. import java.util.concurrent.RecursiveAction;  
  4.   
  5. /** 
  6.  * @author kencs@foxmail.com 
  7.  */  
  8. public class BiSearchWithForkJoin extends RecursiveAction {  
  9.     private final int threshold;  
  10.     private final BinarySearchProblem problem;  
  11.     public int result;  
  12.     private final int numberToSearch;  
  13.       
  14.     public BiSearchWithForkJoin(BinarySearchProblem problem,int threshold,int numberToSearch){  
  15.         this.problem = problem;  
  16.         this.threshold = threshold;  
  17.         this.numberToSearch = numberToSearch;  
  18.     }  
  19.   
  20.     @Override  
  21.     protected void compute() {  
  22.        if(problem.size < threshold){ //小于阀值,就直接用普通的二分查找  
  23.            result = problem.searchSequentially(numberToSearch);  
  24.        }else{  
  25.            //分解子任务  
  26.            int midPoint = problem.size/2;  
  27.            BiSearchWithForkJoin left = new BiSearchWithForkJoin(problem.subProblem(0, midPoint),threshold,numberToSearch);  
  28.            BiSearchWithForkJoin right = new BiSearchWithForkJoin(problem.subProblem(midPoint+1, problem.size),threshold,numberToSearch);  
  29.            invokeAll(left,right);  
  30.            result = Math.max(left.result, right.result);  
  31.        }  
  32.     }  
  33.       
  34.     //构造数据  
  35.     private static final int[] data = new int[1000_0000];  
  36.     static{  
  37.         for(int i = 0;i<1000_0000;i++){  
  38.             data[i] = i;  
  39.         }  
  40.     }  
  41.     public static void main(String[] args){  
  42.        BinarySearchProblem problem = new BinarySearchProblem(data,0,data.length);  
  43.        int threshold = 100;  
  44.        int nThreads = 10;  
  45.        //查找100_0000所在的下标  
  46.        BiSearchWithForkJoin  bswfj = new BiSearchWithForkJoin(problem,threshold,100_0000);  
  47.        ForkJoinPool fjPool = new ForkJoinPool(nThreads);  
  48.        fjPool.invoke(bswfj);  
  49.        System.out.printf("Result is:%d%n",bswfj.result);  
  50.     }  
  51.       
  52.       
  53. }  

  RecursiveTask 还可以带返回值,这里给出一段代码作为参考(斐波那契函数)

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

 

 

Java代码   收藏代码
  1. class Fibonacci extends RecursiveTask<Integer> {  
  2.     final int n;  
  3.   
  4.     Fibonacci(int n) {  
  5.         this.n = n;  
  6.     }  
  7.   
  8.     private int compute(int small) {  
  9.         final int[] results = { 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 };  
  10.         return results[small];  
  11.     }  
  12.   
  13.     public Integer compute() {  
  14.         if (n <= 10) {  
  15.             return compute(n);  
  16.         }  
  17.         Fibonacci f1 = new Fibonacci(n - 1);  
  18.         Fibonacci f2 = new Fibonacci(n - 2);  
  19.         System.out.println("fork new thread for " + (n - 1));  
  20.         f1.fork();  
  21.         System.out.println("fork new thread for " + (n - 2));  
  22.         f2.fork();  
  23.         return f1.join() + f2.join();  
  24.     }  
  25. }  

 

 

用途

    只要问题能够分解成类似子问题的,都可以使用这个框架。对于大批量的数据尤其合适

 

  参考资料

    Jdk7官网 http://openjdk.java.net/projects/jdk7/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值