Fork/Join框架

  1. 主要的Fork/Join类
    • ForkJoinTask<V>:用来定义任务的抽象类
      • ForkJoinTask与Thread不同,ForkJoinTask表示任务的轻量级抽象,而不是执行线程
      • final ForkJoinTask<V> fork()
        • 为调用任务的异步执行提交调用任务,意味着调用fork()方法的线程将持续运行
        • 意味着调用代码不会等待任务完成,相反调用代码将继续异步执行
      • final V join()
        • 等待调用该方法的任务终止,终止结果被返回
        • 调用代码会进行等待,直到有结果返回
      • final V invoke()
        • 将并行(fork)和连接(join)操作合并到单个调用中
        • 返回调用的结果
        • 意味着调用代码进行等待
      • static void invokeAll(ForkJoinTask<?> taskA, ForkJoinTask<?> taskB),  static void invokeAll(ForkJoinTask<?> ... taskList)
      • boolean cancel(boolean interruptOK)
        • 用来取消任务,如果被取消就返回true,不能被取消就返回false
        • 默认实现没有使用interruptOK参数,通常是从任务外部的代码调用cancel()方法
      • final boolean isCancelled()
        • 如果调用任务在结束之前已经取消,就返回true,否则返回false
      • final boolean isCompletedNormally()
      • final boolean isCompletedAbnormally()
      • void reinitialize()
        • 用于重新启动任务
      • static boolean inForkJoinPool()
        • Returns true if the current thread is a ForkJoinWorkerThread executing as a ForkJoinPool computation.
        • 像invokeAll()和fork()这样的方法只能在ForkJoinTask中调用,遵守这条规则通常很容易,但是在有些情况下,可能会具有能够在任务内部或外部执行的代码。可用通过使用inForkJoinPool()方法,确定代码是否在任务内部执行(判断当前线程是否在ForkJoinPool中运行)

    • ForkJoinPool:管理ForkJoinTask的执行
      • 构造函数
        • ForkJoinPool()
          • 创建默认池,支持的并行级别等于系统中可用处理器的数量
        • ForkJoinPool(int pLevel)
          • 指定并行级别
      • 创建好ForkJoinPool实例后,就可以通过大量不同方法开始执行任务,第一个常被认为是主任务
      • 通常由主任务开始其他的由池管理的子任务
      • <T> T invoke(ForkJoinTask<T> task)
        • 一种常用的开始主任务的方式
        • 这个方法开始由task指定的任务,并且返回任务结果。这意味着调用代码会进行等待,直到invoke()方法返回为止
      • void execute(ForkJoinTask<?> task), void execute(Runnable task)
        • 这个方法开始由task指定的任务,但是调用代码不会等待任务完成,相反,调用代码将继续异步执行
      • int getParalleism()
        • 返回当前起作用的并行级别
      • Runtime.getRuntime().availableProcessors()
        • 返回系统中可用处理器的数量
    • RecursiveAction:ForkJoinTask<V>的子类,用于不返回值的任务
      • 通常代码回扩展RecursiveAction以创建具有void返回类型的任务
      • 一般来说,用于为不返回结果的任务实现递归的、分而治之的策略
      • protected abstract void compute()
        • 将定义任务的代码放在compute()中。compute()方法代表任务的计算部分
    • RecursiveTask<V>:ForkJoinTask<V>的子类,用于返回值的任务
      • 一般来说,用于为返回结果的任务实现递归的、分而治之的策略
      • protected abstract V compute()
        • 表示任务的计算部分,将定义任务的代码放到compute()中
  2. 使用RecursiveAction的实例
// A simple example of the basic divide-and-conquer strategy.
// In this case, RecursiveAction is used.
import java.util.concurrent.*;
import java.util.*;

// A ForkJoinTask (via RecursiveAction) that transforms
// the elements in an array of doubles into their square roots.
class SqrtTransform extends RecursiveAction {
  // The threshold value is arbitrarily set at 1,000 in this example.
  // In real world code, its optimal value can be determined by
  // profiling and experimentation.
  final int seqThreshold = 1000;

  // Array to be accessed.
  double[] data;

  // Deterines what part of data to process.
  int start, end;

  SqrtTransform(double[] vals, int s, int e ) {
    data = vals;
    start = s;
    end = e;
  }

  // This is the method in which parallel computation will occur.
  protected void compute() {

    // If number of elements is below the sequential threshold,
    // then process sequentially.
    if( (end - start) < seqThreshold) {
      // Transform each element into its square root.
      for(int i = start; i < end; i++) {
         data[i] = Math.sqrt(data[i]);
      }
    }
    else {
      // Otherwise, continue to break the data into smaller peices.

      // Find the midpoint.
      int middle = (start + end) / 2;

      // Invoke new tasks, using the subdivided data.
      invokeAll(new SqrtTransform(data, start, middle),
                new SqrtTransform(data, middle, end));
    }
  }
}

// Demonstrate parallel execution.
class ForkJoinDemo {
  public static void main(String args[]) {
    // Create a task pool.
    ForkJoinPool fjp = new ForkJoinPool();

    double[] nums = new double[100000];

    // Give nums some values.
    for(int i = 0; i < nums.length; i++)
      nums[i] = (double) i;

    System.out.println("A portion of the original sequence:");

    for(int i=0; i < 10; i++)
      System.out.print(nums[i] + " ");
    System.out.println("\n");

    SqrtTransform task = new SqrtTransform(nums, 0, nums.length);

    // Start the main ForkJoinTask.
    fjp.invoke(task);

    System.out.println("A portion of the transformed sequence" +
                       " (to four decimal places):");
    for(int i=0; i < 10; i++)
      System.out.format("%.4f ", nums[i]);
    System.out.println();
  }
}
  1. RecursiveTask<V>实例
// A simple example that uses RecursiveTask<V>.
import java.util.concurrent.*;

// A RecursiveTask that computes the summation of an array of doubles.
class Sum extends RecursiveTask<Double> {

  // The sequential threshold value.
  final int seqThresHold = 500;

  // Array to be accessed.
  double[] data;

  // Deterines what part of data to process.
  int start, end;

  Sum(double[] vals, int s, int e ) {
    data = vals;
    start = s;
    end = e;
  }

  // Find the summation of an array of doubles.
  protected Double compute() {
    double sum = 0;

    // If number of elements is below the sequential threshold,
    // then process sequentially.
    if( (end - start) < seqThresHold) {
      // Sum the elements.
      for(int i = start; i < end; i++) sum += data[i];
    }
    else {
      // Otherwise, continue to break the data into smaller peices.

      // Find the midpoint.
      int middle = (start + end) / 2;

      // Invoke new tasks, using the subdivided data.
      Sum subTaskA = new Sum(data, start, middle);
      Sum subTaskB = new Sum(data, middle, end);

      // Start each subtask by forking.
      subTaskA.fork();
      subTaskB.fork();

      // Wait for the subtasks to return, and aggregate the results.
      sum = subTaskA.join() + subTaskB.join();
    }
      // Return the final sum.
      return sum;
  }
}

// Demonstrate parallel execution.
class RecurTaskDemo {
  public static void main(String args[]) {
    // Create a task pool.
    ForkJoinPool fjp = new ForkJoinPool();

    double[] nums = new double[5000];

    // Initialize nums with values that alternate between
    // positive and negative.
    for(int i=0; i < nums.length; i++)
      nums[i] = (double) (((i%2) == 0) ? i : -i) ;

    Sum task = new Sum(nums, 0, nums.length);

    // Start the ForkJoinTasks.  Notice that in this case,
    // invoke() returns a result.
    double summation = fjp.invoke(task);

    System.out.println("Summation " + summation);
  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值