介绍一下ForkJoinPool的使用

ForkJoinPool 是 JDK1.7 开始提供的线程池。为了解决 CPU 负载不均衡的问题。如某个较大的任务,被一个线程去执行,而其他线程处于空闲状态。

 

ForkJoinTask 表示一个任务,ForkJoinTask 的子类中有 RecursiveAction 和 RecursiveTask。
RecursiveAction 无返回结果;RecursiveTask 有返回结果。
重写 RecursiveAction 或 RecursiveTask 的 compute(),完成计算或者可以进行任务拆分。

 

调用 ForkJoinTask 的 fork() 的方法,可以让其他空闲的线程执行这个 ForkJoinTask;
调用 ForkJoinTask 的 join() 的方法,将多个小任务的结果进行汇总。

 

无返回值打印任务拆分
 

package constxiong.interview;
 
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;
import java.util.concurrent.TimeUnit;
 
/**
 * 测试 ForkJoinPool 线程池的使用
 * @author ConstXiong
 * @date 2019-06-12 12:05:55
 */
public class TestForkJoinPool {
 
    public static void main(String[] args) throws Exception {
        testNoResultTask();//测试使用 ForkJoinPool 无返回值的任务执行
    }
    
    /**
     * 测试使用 ForkJoinPool 无返回值的任务执行
     * @throws Exception
     */
    public static void testNoResultTask() throws Exception {
        ForkJoinPool pool = new ForkJoinPool();
        pool.submit(new PrintTask(1, 200));
        pool.awaitTermination(2, TimeUnit.SECONDS);
        pool.shutdown();
    }
}
    
/**
 * 无返回值的打印任务
 * @author ConstXiong
 * @date 2019-06-12 12:07:02
 */
class PrintTask extends RecursiveAction {
    
    private static final long serialVersionUID = 1L;
    private static final int THRESHOLD = 49;
    private int start;
    private int end;
    
    public PrintTask(int start, int end) {
        super();
        this.start = start;
        this.end = end;
    }
    
 
    @Override
    protected void compute() {
        //当结束值比起始值 大于 49 时,按数值区间平均拆分为两个任务;否则直接打印该区间的值
        if (end - start <THRESHOLD) {
            for (int i = start; i <= end; i++) {
                System.out.println(Thread.currentThread().getName() + ", i = " + i);
            }
        } else {
            int middle = (start + end) / 2;
            PrintTask firstTask = new PrintTask(start, middle);
            PrintTask secondTask = new PrintTask(middle + 1, end);
            firstTask.fork();
            secondTask.fork();
        }
    }
    
}

 

 

有返回值计算任务拆分、结果合并

package constxiong.interview;
 
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.TimeUnit;
 
/**
 * 测试 ForkJoinPool 线程池的使用
 * @author ConstXiong
 * @date 2019-06-12 12:05:55
 */
public class TestForkJoinPool {
 
    public static void main(String[] args) throws Exception {
        testHasResultTask();//测试使用 ForkJoinPool 有返回值的任务执行,对结果进行合并。计算 1 到 200 的累加和
    }
    
    /**
     * 测试使用 ForkJoinPool 有返回值的任务执行,对结果进行合并。计算 1 到 200 的累加和
     * @throws Exception
     */
    public static void testHasResultTask() throws Exception {
        int result1 = 0;
        for (int i = 1; i <= 200; i++) {
            result1 += i;
        }
        System.out.println("循环计算 1-200 累加值:" + result1);
        
        ForkJoinPool pool = new ForkJoinPool();
        ForkJoinTask task = pool.submit(new CalculateTask(1, 200));
        int result2 = task.get();
        System.out.println("并行计算 1-200 累加值:" + result2);
        pool.awaitTermination(2, TimeUnit.SECONDS);
        pool.shutdown();
    }
    
}
 
/**
 * 有返回值的计算任务
 * @author ConstXiong
 * @date 2019-06-12 12:07:25
 */
class CalculateTask extends RecursiveTask {
 
    private static final long serialVersionUID = 1L;
    private static final int THRESHOLD = 49;
    private int start;
    private int end;
    
    public CalculateTask(int start, int end) {
        super();
        this.start = start;
        this.end = end;
    }
 
    @Override
    protected Integer compute() {
        //当结束值比起始值 大于 49 时,按数值区间平均拆分为两个任务,进行两个任务的累加值汇总;否则直接计算累加值
        if (end - start <= THRESHOLD) {
            int result = 0;
            for (int i = start; i <= end; i++) {
                result += i;
            }
            return result;
        } else {
            int middle = (start + end) / 2;
            CalculateTask firstTask = new CalculateTask(start, middle);
            CalculateTask secondTask = new CalculateTask(middle + 1, end);
            firstTask.fork();
            secondTask.fork();
            return firstTask.join() + secondTask.join();
        }
    }
    
}

 


原文链接
 


  • Java 自学指南
  • Java 面试题汇总PC端浏览【点这里】
  • Java知识图谱
  • Java 面试题汇总小程序浏览,扫二维码

介绍一下ForkJoinPool的使用_第1张图片

 

所有资源资源汇总于公众号

介绍一下ForkJoinPool的使用_第2张图片

 

 

你可能感兴趣的:(介绍一下ForkJoinPool的使用)