Java 并发基础 (九)-Fork/Join 框架

1,669 阅读2分钟
原文链接: blog.csdn.net

1. 什么是Fork/Join框架

Java 1.7 中提供了Fork/Join框架,实现了work-stealing算法(工作窃取算法),什么意思呢?就是说,我可以把当前任务分割成多个小任务,让空闲的线程也进行工作,是不是很赞,这样,就能最大限度的利用资源,从而提升效率。

哈,这里就补全线程池基础那篇文章了,java 1.8 提供的newWorkStealingPool,就是用这个实现的。

2. 包括哪些内容呢

包括一下内容:

  • ForkJoinPool 实现工作窃取算法的线程池
  • ForkJoinTask ForkJoinPool中执行的任务的基类,这个类中有几个比较重要的方法,根据不同的需求去实现他的两个子类
  • RecursiveAction ForkJoinTask的一个子类,含任务执行结果
  • RecursiveTask ForkJoinTask的另一个子类,不含任务执行结果
    • 我们都需要实现这两个子类的 compute方法,更具需求切分任务

我这里就不在介绍api了,有兴趣的同学自行fuck 文档或者源码中的注释。

3.举个例子?

举个例子来说明效率的提升。举个什么样的例子呢?遍历文件,这个好。看下普通用法和输出结果(一会对比输出结果)。

    private static void noForkJoin(){
        File file = new File("/home/guolei/geek");
        long start = System.currentTimeMillis();
        long length = getFileCount(file);
        System.err.println("noForkJoin ----> 文件数目"+length);
        System.err.println( "noForkJoin ----> 耗时" + (System.currentTimeMillis() - start) + "ms");
    }

    private static long getFileCount(File file){
        long count = 0;
        File[] files = file.listFiles();
        for (int i = 0; i < files.length; i++) {
            if (files[i].isDirectory()){
               count += getFileCount(files[i]);
            }else {
                count ++;
            }
        }
        return count;
    }

装b程序员写法:

1 首先,我们得实现RecursiveTask,因为我们需要结果。

    private static class CustomTask extends RecursiveTask{

        private File file;
        public CustomTask(File file){
            this.file = file;
        }
        @Override
        protected Long compute() {
            long count = 0L;
            File[] files = file.listFiles();
            for (int i = 0; i < files.length; i++) {
                if (files[i].isDirectory()){

                        CustomTask customTask = new CustomTask(files[i]);
                        customTask.fork();
                        count += customTask.join();

                }else {
                    count ++;
                }
            }
            return count;

2 其次,我们创建ForkJoinPool和Task并执行,

        File file = new File("/home/guolei/geek")
        long start = System.currentTimeMillis()
        ForkJoinPool forkJoinPool = new ForkJoinPool()
        CustomTask customTask = new CustomTask(file)
        Future future = forkJoinPool.submit(customTask)
        try {
            System.err.println("forkJoin -----> 文件数目" + future.get())
        } catch (InterruptedException e) {
            e.printStackTrace()
        } catch (ExecutionException e) {
            e.printStackTrace()
        }
        System.err.println( "forkJoin -----> 耗时" + (System.currentTimeMillis() - start) + "ms")

代码就这么一点,那么我们来对比下耗时。截图如下:

这里写图片描述

我这里文件还不是很多,但是提升已经很明显了。。。

有没有get到这个技能呢?拿去!!!