加速Java

时间:2015-09-12 19:09:03

标签: java multithreading hash

我正在开发一个管理备份的程序。

为此,我研究了一种方法,该方法散列(MD5)必须检查的磁盘的每个文件,以检测是否有副本,因为我想检测它们并通知用户。我按照here所述使用了apache库。

问题是该程序应该管理来自许多不同类型(视频,音乐,字母,您可能想要备份的所有内容)的大量数据,因此哈希的时间可能会变得很长(我计算了大型视频的哈希值) 1.6 Gb,需要将近25秒。

所以你可以想象散布数百个Gigs的时间......

我已经尝试用线程拆分工作,在“相同”时间内散列很多文件,这是我的run()方法:

public void run() {
    running = true;
    while (running) {
        System.out.println("Thread: " + this.getName() + " starting");
        files = path.listFiles();
        if (files != null) {
            for (File file : files) {
                if (file.isDirectory()) {
                    System.out.println(file.getName());
                    dtm.countDirectory();
                    DetectorThread dt = new DetectorThread(dtm, file);
                    dt.start();
                    dtm.resetTimer();
                } else if (file.isFile()) {
                    String hash = h.hash(file.getAbsolutePath());
                    System.out.println(file.getName() + "\t" + hash);
                    dtm.countFile();
                    dtm.addFile(file, hash);
                    dtm.resetTimer();
                }
            }
        }
        dtm.resetTimer();
        running = false;
        System.out.println("Thread: " + this.getName() + " terminated");
    }
}

你给线程一个路径,他将为每个子文件夹启动另一个线程。

使用这段代码,我以不到100 Gigs的35分钟工作结束,所以我想知道是否有更简单的方法来查找文件的唯一ID,检测副本或更快的方式来哈希或者我做了线程有问题。

任何想要加速这种治疗的想法都是受欢迎的。

提前谢谢。

PS:我的电脑还不错,所以不是表演。

2 个答案:

答案 0 :(得分:0)

实际上没有必要哈希一切。

首先查看文件大小。如果没有其他文件具有相同的大小,则您的检查已完成,并且您不会浪费时间扫描整个文件以对其进行哈希处理。

大文件的大小很可能是唯一的,因此您最终可能只会散列一些较小的文件。

仅供参考:您的性能很可能完全受磁盘限制,这意味着多线程代码花费大部分时间等待硬盘返回数据。

您可以通过监控系统来确认。硬盘指示灯将保持亮起(不会像往常一样闪烁),CPU将处于空闲状态。

更快的方法就是少阅读。

答案 1 :(得分:0)

在我看来,这段代码会创建太多线程。每个线程创建都具有相对高成本。

此外,太多线程同时读取文件会导致I / O效率低下:当一个线程读取一堆数据时,系统通常会在缓存中加载一个完整的块,以加快即将到来的访问。当许多线程同时读取大块时,系统将丢弃这些缓存,强制额外的磁盘访问。

快速简便的解决方法是使用ThreadPool,将可执行线程的数量限制为修订号。理想的数字可能在您的CPU核心数量附近。您的DetectorThread必须实施Callable

如果大多数大文件存储在有限数量的目录中,您将面临另一个问题:单个线程必须按顺序解析它们。最好让一个单独的线程递归扫描目录,为每个文件创建一个Callable。