ForkJoin的使用——让多个任务并行执行

69 阅读1分钟

文章目录

写在前面

开发中遇到这么一个业务场景:有100个任务我需要执行,这几个任务之间并没有什么关联,只需要在这些任务都执行完毕之后,我需要一个最终的结果。
此时,就需要使用ForkJoin线程池来完成多个任务并行的工作了,大大的提高了运行速度!

直接上代码


import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;

/**
 * 在项目中使用forkjoin
 */
public class UseForkJoin {


    public static void main(String[] args) {
    	// 创建一个可以同时执行20个线程的ForkJoinPool
        ForkJoinPool pool = new ForkJoinPool(20);
        // 初始化需要执行的数据
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 200; i ++) {
            list.add(i);
        }
        pool.invoke(new ExecuteService(list, 0, list.size()));
        System.out.println("活跃线程数:"+pool.getActiveThreadCount());
        System.out.println("窃取任务数:"+pool.getStealCount());

    }


}

/**
 * 业务逻辑类
 */
class ExecuteService extends RecursiveAction {
    // 拆分粒度
    static final int THRESHOLD = 4;
    List<Integer> list;
    // 开始
    int start;
    // 结束
    int end;

    public ExecuteService(List<Integer> list, int start, int end) {
        this.list = list;
        this.start = start;
        this.end = end;
    }

    @Override
    protected void compute() {
    	// 判断是否需要继续分割任务
        int length = end - start;
        if(length <= THRESHOLD){
            for (int i = start; i <= end; i++) {
                // 执行业务逻辑
                System.out.println(Thread.currentThread().getName() + "计算" + i);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        else {
            // 继续拆分
            int middle = (start + end) / 2;
            ExecuteService left = new ExecuteService(list, start, middle);
            left.fork(); // 执行任务
            ExecuteService right = new ExecuteService(list, middle + 1, end);
            right.fork(); // 执行任务
            left.join(); // 必须得join
            right.join();
        }
    }
}

解析

这里我们让业务类继承的是RecursiveAction ,它是可以执行返回值是void的任务,同时jdk也提供了可以有返回值的类RecursiveTask。