分治思想ForkJoin

Posted by     小兵兵 on Thursday, June 11, 2020

目录

分治思想ForkJoin

求和汇总结果

遍历指定目录查找指定类型文件

package com.zbiti.juc;

import java.io.File;
import java.util.ArrayList;
import java.util.concurrent.*;

public class ForkJoinTaskTest {
    public static void main(String[] args) {
//        forkJoinSum();
//        normalSum();
        forkJoinFindFile();

    }

    //查找指定类型文件
    private static void forkJoinFindFile() {
        //1、创建池
        ForkJoinPool forkJoinPool = new ForkJoinPool();
        //2、创建任务
        FindDirsFiles task = new FindDirsFiles(new File("D:/"));
        //4、执行任务,异步执行
        forkJoinPool.execute(task);
        task.join();
    }

    private static void normalSum() {
        System.out.println("当前线程" + Thread.currentThread().getName() + "\t 干活");
        long start_time2 = System.currentTimeMillis();
        int sum = 0;
        for (int i = 1; i <= 100; i++) {
            sum += i;
            //模拟执行任务时间
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(sum);
        long end_time2 = System.currentTimeMillis();
        long resumeTime = end_time2 - start_time2;
        System.out.println("常规求和时间:" + resumeTime);
    }

    private static void forkJoinSum() {
        long start_time = System.currentTimeMillis();
        //1、创建池
        ForkJoinPool forkJoinPool = new ForkJoinPool();
        //2、创建任务
        MySumTask mySumTask = new MySumTask(1, 100);
        //4、执行任务,包含同步执行、异步执行
        //同步
//        Integer result = forkJoinPool.invoke(mySumTask);
//        System.out.println(result);
        //异步
        ForkJoinTask<Integer> submit = forkJoinPool.submit(mySumTask);
        try {
            //调用get获取结果需要等任务执行完成,此时会阻塞后面的线程
            Integer result = submit.get();
            System.out.println(result);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        long end_time = System.currentTimeMillis();
        long resumeTime = end_time - start_time;
        System.out.println("分治求和时间:" + resumeTime);
    }
}

/**
 * 分治思想  求和汇总结果 同步|异步执行  带返回值
 */
class MySumTask extends RecursiveTask<Integer> {
    private int size = 20;
    private int start;
    private int end;
    private int sum;
    private int middleSum;

    public MySumTask(int start, int end) {
        this.start = start;
        this.end = end;
    }

    @Override
    protected Integer compute() {
        boolean canCompute = end - start <= size;
        if (canCompute) {
            System.out.println("当前线程" + Thread.currentThread().getName() + "\t 处理数据开始节点" + start + "\t 处理数据结束节点" + end);
            for (int i = start; i <= end; i++) {
                sum += i;
                //模拟任务执行时间
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return sum;

        } else {
            //3、拆分任务到能够执行的条件
            int middle = end + start >> 1;
            MySumTask leftTask = new MySumTask(start, middle);
            MySumTask rightTask = new MySumTask(middle + 1, end);
            //执行子任务
            invokeAll(leftTask, rightTask);
            //汇总子任务结果
            Integer leftResult = leftTask.join();
            Integer rightResult = rightTask.join();
            middleSum = leftResult + rightResult;
        }
        return middleSum;
    }
}

/**
 * 分治思想  遍历指定目录(含子目录)找寻指定类型文件
 * 同步|异步执行  不带返回值
 */
class FindDirsFiles extends RecursiveAction {
    private File path;

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

    @Override
    protected void compute() {
        ArrayList<FindDirsFiles> subTasks = new ArrayList<>();
        File[] files = path.listFiles();
        if (files != null) {
            for (File file : files) {
                if (file.isDirectory()) {
                    //对每个子目录都新建一个子任务
                    subTasks.add(new FindDirsFiles(file));
                } else {
                    //遇到文件,检查
                    if (file.getAbsolutePath().endsWith(".txt")) {
                        System.out.println("当前线程" + Thread.currentThread().getName() + "\t 文件:" + file.getAbsolutePath());
                    }
                }
            }
            //执行子任务,合并子任务结果
            if (!subTasks.isEmpty()) {
                for (FindDirsFiles subTask : invokeAll(subTasks)) {
                    subTask.join();
                }
            }

        }

    }
}