【问题标题】:Comparing Fork And Join with Single threaded program比较 Fork 和 Join 与单线程程序
【发布时间】:2015-03-12 16:58:22
【问题描述】:

我正在尝试开始使用 Fork-Join 框架来完成一项较小的任务。当我启动示例时,我尝试复制 mp3 文件

import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

public class DeepFileCopier extends RecursiveTask<String>{

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    private static Path startingDir = Paths.get("D:\\larsen\\Music\\");
    private static List<Path> listOfPaths = new ArrayList<>();
    private int start, end;

    public static void main(String[] args) throws IOException
    {
        long startMillis = System.currentTimeMillis();
        Files.walkFileTree(startingDir, new CustomFileVisitor());
        final DeepFileCopier deepFileCopier = new DeepFileCopier(0,listOfPaths.size());
        final ForkJoinPool pool = new ForkJoinPool(Runtime.getRuntime().availableProcessors());
        pool.invoke(deepFileCopier);
        System.out.println("With Fork-Join " + (System.currentTimeMillis() - startMillis));
        long secondStartMillis = System.currentTimeMillis();
        deepFileCopier.start = 0;
        deepFileCopier.end = listOfPaths.size();
        deepFileCopier.computeDirectly();
        System.out.println("Without Fork-Join " + (System.currentTimeMillis() - secondStartMillis));

    }

    private static class CustomFileVisitor extends SimpleFileVisitor<Path> {
        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException
        {
            if (file.toString().endsWith(".mp3")) {
                listOfPaths.add(file);
            }
            return FileVisitResult.CONTINUE;
        }
    }

    @Override
    protected String compute() {
        int length = end-start;
        if(length < 4) {
            return computeDirectly();
        }
        int split = length / 2;
        final DeepFileCopier firstHalfCopier = new DeepFileCopier(start, start + split);
        firstHalfCopier.fork();
        final DeepFileCopier secondHalfCopier = new DeepFileCopier(start + split, end);
        secondHalfCopier.compute();
        firstHalfCopier.join();
        return null;
    }

    private String computeDirectly() {
        for(int index = start; index< end; index++) {
            Path currentFile = listOfPaths.get(index);
            System.out.println("Copying :: " + currentFile.getFileName()); 
            Path targetDir = Paths.get("D:\\Fork-Join Test\\" + currentFile.getFileName());
            try {
                Files.copy(currentFile, targetDir, StandardCopyOption.REPLACE_EXISTING);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    private DeepFileCopier(int start, int end ) {
        this.start = start;
        this.end = end;
    }

}

比较我注意到的性能 -

带叉连接 149714 没有 Fork-Join 146590

我正在研究双核机器。我预计工作时间会减少 50%,但使用 Fork-Join 的部分比单线程方法多花 3 秒。如果有什么不对的地方请告诉我。

【问题讨论】:

    标签: java multithreading fork-join


    【解决方案1】:

    您的问题不太适合从普通系统上的多线程中受益。执行时间用于复制所有文件。但这受到您的硬盘驱动器的限制,它将按顺序处理文件。

    如果您运行 CPU 密集度更高的任务,您应该注意到其中的差异。出于测试目的,您可以尝试以下操作:

    private String computeDirectly() {
       Integer nonsense;
       for(int index = start; index< end; index++) {
          for( int j = 0; j < 1000000; j++ )
             nonsense += index*j;
        }
        return nonsense.toString();
    }
    

    在我的系统 (i5-2410M) 上会打印:

    With Fork-Join 2628
    Without Fork-Join 6421
    

    【讨论】:

      猜你喜欢
      • 2014-02-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-04
      • 2010-11-17
      • 1970-01-01
      相关资源
      最近更新 更多