Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用线程并发散列(sha1)多个文件_Java_Multithreading_Sha1_Java 7 - Fatal编程技术网

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

Java 使用线程并发散列(sha1)多个文件,java,multithreading,sha1,java-7,Java,Multithreading,Sha1,Java 7,我有N个大文件(不少于2.5亿个)要散列。这些文件位于P物理驱动器上 我想用最多K个活动线程同时散列它们,但我不能在每个物理驱动器上散列超过M个文件,因为这会减慢整个过程(我运行了一个测试,解析了61个文件,使用8个线程比使用1个线程慢;文件几乎都在同一磁盘上) 我想知道最好的方法是什么: 我可以使用Executors.newFixedThreadPool(K) 然后,我将使用计数器提交任务,以确定是否应添加新任务 我的代码是: int K = 8; int M = 1; Queue<

我有N个大文件(不少于2.5亿个)要散列。这些文件位于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);
}
intk=8;
int M=1;
队列=null;//让文件散列
final ExecutorService newFixedThreadPool=Executors.newFixedThreadPool(K);
最终ConcurrentMap计数器=新ConcurrentHashMap();
最终ConcurrentMap maxCounter=新ConcurrentHashMap();
对于(文件存储区:FileSystems.getDefault().getFileStores()){
计数器。放置(存储,0);
最大计数器放置(存储,M);
}
列表结果=新建ArrayList();
而(!queue.isEmpty()){
最终路径当前=queue.poll();
final FileStore store=Files.getFileStore(当前);
if(counter.get(store)
抛开潜在的非线程安全操作(比如我如何使用计数器),有没有更好的方法来实现我的目标


我还认为这里的循环可能有点太多,因为它可能会占用大量的进程(几乎像一个无限循环)。

如果驱动器硬件配置在编译时未知,并且可能会被更改/升级,那么很有可能会对每个驱动器使用线程池,并让线程数由用户配置。我不熟悉“newFixedThreadPool”-线程计数是一个可以在运行时更改以优化性能的属性吗?

经过很长时间,我找到了一个解决方案来满足我的需要:而不是整数计数器,或
原子整数
或其他什么,我使用了一个
ExecutorService
,每个提交的任务都在一个驱动器的每个文件中使用一个共享

比如:

ConcurrentMap=new ConcurrentHashMap();
Executors服务es=Executors.newFixedThreadPool(10);
对于(路径:listFile()){
final FileStore store=Files.getFileStore(路径);
final Semaphore Semaphore=map.computeIfAbsent(存储,键->新信号量(getAllocatedCredits(存储));
最终整数成本=计算成本(路径);
提交(()->{
信号量获取(成本);
试一试{
…一些工作。。。
}最后{
信号量释放(成本);
}
});
}
int getAllocatedCredits(文件存储区){return 2;}
int computeCost(路径){return 1;}

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

中,您知道哪个驱动器上有哪个文件吗?我只需要为每个驱动器分配一个线程,让它处理该驱动器上的所有文件。是的,每个驱动器一个线程可能是可行的。是的。事实上,FileStore提供了逻辑驱动器(可能是物理驱动器,也可能不是物理驱动器)。最后,我想在一个有5个驱动器的RAID的NAS上运行我的代码,这将允许更多的文件被散列。作为旁注,使用
do{int count=counter.get(store);}而(!counter.replace(store,count,count+1))而不是get/put(替换是concurrentmap的CompareAndSwap)我concur:每个驱动器一个可防止磁头移位。优先级队列也很好,可以防止拥塞。优先级基于队列中的时间和负文件大小:与已处理的累积大小类似-队列条目的文件大小。我简化了我的示例,但我打算让用户(我自己^^)更改最大线程数(如果超线程,则更改核心数*2)和每个磁盘的最大线程数。
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;}