Java并发编程——ForkJoinPool实战演练

ForkJoinPool体现了分而治之的思想,将一个大事件,拆分成若干个小事件去处理,执行完成后,再将一个个小事件执行的结果合并到一起。

使用方法:

1、创建ForkJoinPool实例

2、通过submit方法、invoke方法、invokeAll方法来执行指定任务。

  • T invoke(ForkJoinTask<T> task)执行给定的任务,在完成后返回其结果。
  • List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)执行给定的任务,返回持有他们的状态和结果的所有完成的任务列表。
  • ForkJoinTask<T> submit(Callable<T> task)提交并执行,并返回任务处理结果的Future。  
  • ForkJoinTask<T> submit(ForkJoinTask<T> task)提交一个ForkJoinTask来执行。  
  • ForkJoinTask<?> submit(Runnable task)提交一个可运行的任务执行,并返回一个表示该任务的结果。  
  • ForkJoinTask<T> submit(Runnable task, T result)提交一个可运行的任务执行,并返回一个表示该任务的结果。

3、ForkJoinTask:代表一个可以并行、合并的任务。ForkJoinTask是一个抽象类,它还有两个抽象子类:RecusiveAction和RecusiveTask。其中RecusiveTask代表有返回值的任务,而RecusiveAction代表没有返回值的任务。

代码演示(此处只演示有返回值的情况):

package com.alex.fork;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

/**
 *  搜索指定文件信息
 *  @author: alex
 *  @Date:  2019/3/20 9:52
 *  @Description: 演示RecursiveTask的用法,将大事件拆分成若干个小任务去执行,执行完成后使用ForkJoinPool,合并结果集
 *  场景描述:搜索指定文件名,获得该文件名所在的目录。
 *  将每一层的文件夹都当做一个子任务进行拆分,寻找每个子文件夹中的内容,最后合并结果集。
 */
public class SearchFiles extends RecursiveTask<String> {

    private File path;
    private String searchFileName;

    /**
     * 构造方法
     * @param path 文件信息
     * @param searchFileName 目标文件名字
     */
    public SearchFiles(File path, String searchFileName) {
        this.path = path;
        this.searchFileName = searchFileName;
    }

    /**
     * 重新compute方法
     * @return 结果
     */
    @Override
    protected String compute() {
        String filePath = "";  //存放文件路径
        List<SearchFiles> subTask = new ArrayList<SearchFiles>(); //子任务集合
        File[] files = path.listFiles();
        for (File file : files) {
            //判断是否是文件夹,如果是,则添加到子任务集合中,不是,则判断是否是目标文件
            if (file.isDirectory()) {
                subTask.add(new SearchFiles(file, searchFileName));
            } else {
                if (file.getName().equals(searchFileName)) { //是否是目标文件
                    filePath = file.getAbsolutePath(); //返回目标文件路径
                }
            }
        }
        //判断子任务集合是否为空
        if (!subTask.isEmpty()) {
            //通过invokeAll方法,执行所有子任务
            for (SearchFiles task : invokeAll(subTask)) {
                if (!task.join().isEmpty()) {
                    filePath = filePath + task.join() + ",";
                }
            }
        }
        return filePath;
    }

    /**
     * 搜索目标文件
     * @param path 文件路径
     * @param fileName 目标文件名称
     * @return 目标文件路径集合
     */
    public static List<String> searchFileByName(String path, String fileName) {
        ForkJoinPool forkJoinPool = new ForkJoinPool();
        SearchFiles findDirFiles = new SearchFiles(new File(path), fileName);
        forkJoinPool.invoke(findDirFiles);
        String result = findDirFiles.join();
        List<String> resultList = new ArrayList<>();
        if (!result.isEmpty()) {
            for (String name : result.split(",")) {
                if (!name.isEmpty()) {
                    resultList.add(name);
                }
            }
        }
        return resultList;
    }
}

 测试类:

package com.alex.fork;

import java.util.List;

/**
 * 搜索指定文件的测试方法
 */
public class SearchFilesTest {
    public static void main(String[] args) {
        List<String> list = SearchFiles.searchFileByName("F:\\106other", "下载说明.txt");
        list.forEach(System.out::println);
//        for (String s : list) {
//            System.out.println(s);
//        }
    }

}

 运行结果:

F:\106other\visualvm-ml\下载说明.txt
F:\106other\推荐人简历\下载说明.txt

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值