并发编程---- Fork-Join框架

什么是分而治之?

规模为N的问题,N<阈值,直接解决,N>阈值,将N分解为K个小规模子问题,子问题互相对立,与原问题形式相同,将子问题的解合并得到原问题的解。
并发编程---- Fork-Join框架_第1张图片

工作密取

当有线程子任务结束后,该线程就会从子任务的队列中密取最后的任务继续执行。

Fork/Join使用的标准范式

并发编程---- Fork-Join框架_第2张图片

Fork/Join的同步用法(invoke)

需求:计算一个数组中所有元素的和。

package com.jym.thread.forkJoin;

import java.util.Random;

/**
 * @program: jym-concurrent
 * @description: 创建一个数字的工具类
 * @author: jym
 * @create: 2020/05/22
 */
public class MakeArray {

    public static final Integer ARRAY_COUNT = 40000000;

    public static int[] make() {
        int[] arrays = new int[ARRAY_COUNT];
        Random random = new Random();
        for (int i = 0; i < ARRAY_COUNT; i++) {
            int num = random.nextInt(ARRAY_COUNT * 3+10000);
            arrays[i] = num;
        }
        return arrays;
    }

}
package com.jym.thread.forkJoin;

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

/**
 * @program: jym-concurrent
 * @description: 继承 RecursiveTask 类,返回值类型为 Integer
 * @author: jym
 * @create: 2020/05/22
 */
public class ArrayTsk extends RecursiveTask<Integer> {

    public static Integer count = MakeArray.ARRAY_COUNT;
    // 需要计算的数组
    private int[] ints;
    // 开始计算数组的索引
    private int start;
    // 结束数组的索引
    private int end;

    public ArrayTsk(int[] ints, int start, int end) {
        this.ints = ints;
        this.start = start;
        this.end = end;
    }

    @Override
    protected Integer compute() {
        int length = end - start;
        int sum = 0;
        if (length > count) {
            for (int i = start; i <= end; i++) {
                sum = sum + ints[i];
            }
            return sum;
        } else {  // 超过阈值,开始拆分。
            int middle = (start + end)/2;
            ArrayTsk left = new ArrayTsk(ints,middle,end);
            ArrayTsk right = new ArrayTsk(ints,start,middle);
            invokeAll(left,right);
            // 合并结果。
            return left.join() + right.join();
        }
    }

    public static void main(String[] args) {
        int[] ints = MakeArray.make();
        ForkJoinPool forkJoinPool = new ForkJoinPool();
        ArrayTsk arrayTsk = new ArrayTsk(ints,0,MakeArray.ARRAY_COUNT-1);
        long l = System.currentTimeMillis();
        // invoke 同步方法,会阻塞。执行任务。
        Integer integer = forkJoinPool.invoke(arrayTsk);
        System.out.println("共耗时:" + (System.currentTimeMillis()-l));
        System.out.println(integer);
    }
}
Fork/Join的异步用法(execute)

需求:遍历指定目录(含子目录)寻找指定类型文件

package com.jym.thread;

import java.io.File;
import java.util.ArrayList;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;

/**
 * @program: jym-concurrent
 * @description: 继承 RecursiveAction 类,无返回值用法
 * @author: jym
 * @create: 2020/06/02
 */
public class UseForkJoin1 extends RecursiveAction {

    private File path;

    public UseForkJoin1(File path) {
        this.path = path;
    }

    @Override
    protected void compute() {
        if (null != path) {
            File[] files = path.listFiles();
            // 子任务集合,每一个文件夹都为一个子任务。
            ArrayList<UseForkJoin1> useForkJoin1s = new ArrayList<>();
            if (files != null) {
                for (File file : files) {
                    if (file.isDirectory()) {
                        UseForkJoin1 useForkJoin1 = new UseForkJoin1(file);
                        useForkJoin1s.add(useForkJoin1);
                    } else {
                        System.out.println("文件名为:" + file.getName());
                    }
                }
                // 执行子任务。
                if (!useForkJoin1s.isEmpty()) {
                    for (UseForkJoin1 useForkJoin1 : invokeAll(useForkJoin1s)) {
                        useForkJoin1.join();
                    }
                }
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        UseForkJoin1 useForkJoin1 = new UseForkJoin1(new File("G:\\BaiduNetdiskDownload"));
        ForkJoinPool forkJoinPool = new ForkJoinPool();
        forkJoinPool.execute(useForkJoin1);

        System.out.println("task is running ..........");
        Thread.sleep(10000);
        System.out.println("task is end ..........");
    }
}

你可能感兴趣的:(多线程)