Java 多线程进阶-并发编程(三) ForkJoinPool(JDK7以上)

  • ForkJoinPool
    • Java7 提供另一种并行框架: 分解/治理/合并(分治编程)
    • 适用于一种特殊任务, 这类任务的计算量不好确定(最小任务可确定)
    • 关键类
      • ForkJoinPool 任务池
      • RecursiveAction
      • RecursiveTask
    • 代码示例
      package thread0418;
      
      import java.time.LocalDateTime;
      import java.util.concurrent.ExecutionException;
      import java.util.concurrent.ForkJoinPool;
      import java.util.concurrent.ForkJoinTask;
      import java.util.concurrent.RecursiveTask;
      
      /**
       * 分任务求和
       * 使用 java.util.concurrent.ForkJoinPool (分治编程)
       * 使用 RecursiveTask (可以递归的任务接口)
       * 1) 把任务分解 一直分解直到 分解到上下限差值小于等于5
       * 2) 完成任务
       * 3) 把结果合并
       */
      public class ForkJoinPoolDemo1 {
          public static void main(String[] args) throws ExecutionException, InterruptedException {
              // 创建执行线程池
              ForkJoinPool pool = new ForkJoinPool();
      //        ForkJoinPool pool = new ForkJoinPool(4); // parallelism
      
              // 创建任务
              SumTask111 task = new SumTask111(1, 100000000);
      
              // 提交任务
              ForkJoinTask<Long> result = pool.submit(task);
      
              do {
                  System.out.printf(LocalDateTime.now() + " => " + "Main: PoolActiveThreadCount:%d" + "\n", pool.getActiveThreadCount());
                  System.out.printf(LocalDateTime.now() + " => " + "Main: 并行度(PoolParallelism): %d" + "\n", pool.getParallelism());
                  try {
                      Thread.sleep(50);
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
              } while (!task.isDone());
      
              // 输出结果
              System.out.println(LocalDateTime.now() + " => " + result.get().toString());
          }
      }
      
      class SumTask111 extends RecursiveTask<Long> {
          private int start;
          private int end;
      
          public SumTask111(int start, int end) {
              this.start = start;
              this.end = end;
          }
      
          public static final int threadHold = 5;
      
          @Override
          protected Long compute() {
              long sum = 0L;
              // 如果任务足够小, 直接执行
              boolean canCompute = (end - start) <= threadHold;
              if (canCompute) {
                  for (int i = start; i <= end; i++) {
                      sum = sum + i;
                  }
              } else {
                  // 任务大于阈值, 分裂为 2 个任务
                  int middle = (start + end) / 2;
                  SumTask111 subTask1 = new SumTask111(start, middle);
                  SumTask111 subTask2 = new SumTask111(middle + 1, end);
      
                  invokeAll(subTask1, subTask2);
      
                  Long sum1 = subTask1.join();
                  Long sum2 = subTask2.join();
      
                  // 结果合并
                  sum = sum1 + sum2;
              }
              return sum;
          }
      }
    
    
  • 总结
    • 了解 Fork-Join 和Executor 的区别
    • 控制任务分解粒度
    • 熟悉 Fork-Join 框架, 提高多线程执行效率.

posted on 2020-04-18 15:40  Sweet小马  阅读(270)  评论(0编辑  收藏  举报

导航