繁体   English   中英

使用线程并发地散列(sha1)多个文件

[英]Hashing (sha1) multiple file concurrently using threads

哈希有N个大文件(不少于250M)。 这些文件位于P物理驱动器上。

我想同时使用最大K个活动线程对它们进行哈希处理,但是我不能为每个物理驱动器散列超过M个文件,因为它会减慢整个过程(我运行测试,解析61个文件,并且使用8个线程,它比1个线程;文件几乎都在同一个磁盘上)。

我想知道最好的方法是什么:

  • 我可以使用Executors.newFixedThreadPool(K)
  • 然后我会使用计数器提交任务,以确定是否应该添加新任务。

我的代码是:

int K = 8;
int M = 1;
Queue<Path> queue = null; // get the files to hash
final ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(K);
final ConcurrentMap<FileStore, Integer> counter = new ConcurrentHashMap<>();
final ConcurrentMap<FileStore, Integer> maxCounter = new ConcurrentHashMap<>();
for (FileStore store : FileSystems.getDefault().getFileStores()) {
  counter.put(store, 0);
  maxCounter.put(store, M);
}
List<Future<Result>> result = new ArrayList<>();
while (!queue.isEmpty()) {
  final Path current = queue.poll();
  final FileStore store = Files.getFileStore(current);
  if (counter.get(store) < maxCounter.get(store)) {
    result.add(newFixedThreadPool.submit(new Callable<Result>() {

      @Override
      public Entry<Path, String> call() throws Exception {
        counter.put(store, counter.get(store) + 1);
        String hash = null; // Hash the file
        counter.put(store, counter.get(store) - 1);
        return new Result(path, hash);
      }

    }));
  } else queue.offer(current);
}

抛开潜在的非线程安全操作(比如我如何使用计数器),是否有更好的方法来实现我的目标?

我也认为这里的循环可能有点过多,因为它可能会占用很多进程(几乎就像一个无限循环)。

经过很长时间,我找到了一个解决方案来实现我的需求:我使用了ExecutorService ,而不是整数计数器,或AtomicInteger ,每个提交的任务使用一个驱动器的每个文件共享的Semaphore

喜欢:

ConcurrentMap<FileStore, Semaphore> map = new ConcurrentHashMap<>();
ExecutorService es = Executors.newFixedThreadPool(10);
for (Path path : listFile()) {
  final FileStore store = Files.getFileStore(path);
  final Semaphore semaphore = map.computeIfAbsent(store, key -> new Semaphore(getAllocatedCredits(store)));
  final int cost = computeCost(path);
  es.submit(() -> {
    semaphore.acquire(cost);
    try {
      ... some work ...
    } finally {
      semaphore.release(cost);
    }
  });
}


int getAllocatedCredits(FileStore store) {return 2;}
int computeCost(Path path) {return 1;}

请注意Java 8的帮助,特别是在computeIfAbsentsubmit

如果在编译时未知驱动器硬件配置,并且可能是chaged / upgrade,那么每个驱动器使用一个线程池并使用户可配置的线程计数很有诱惑力。 我不熟悉'newFixedThreadPool' - 线程数是一个可以在运行时更改以优化性能的属性吗?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM