Java利用多线程计算目录数据大小(4)

5 线程安全且简洁高效扫描

最后我们使用ForkJoinTask来完成目录计算扫描。所谓ForkJoinTask,顾名思义,就是线程间协同合作。Fork-join API主要用于处理那些规模合理的任务,即如果每个任务所分担的开销不大,则该API就可以达到合理的吞吐量。同时,其也希望所有任务都不要有副作用(如改变共享变量)并且没有同步或锁操作。如下例子:

package gibbon.thread;

import Java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.TimeoutException;

public class FileSize {
 private final static ForkJoinPool forkJoinPool = new ForkJoinPool();
 
 private static class FileSizeFinder extends RecursiveTask<Long>{
  File file;
  public FileSizeFinder(File file){
   this.file = file;
  }
 
  @Override
  protected Long compute() {
   // TODO Auto-generated method stub
   long size = 0;
   if(file.isFile()){
    return file.length();
   }else{
    File[] children = file.listFiles();
    if(children != null){
     List<ForkJoinTask<Long>> tasks = new ArrayList<ForkJoinTask<Long>>();
     for(File child:children){
      if(child.isFile()){
       size += child.length();
      }else{
       tasks.add(new FileSizeFinder(child));
      }
     }
     
     for(ForkJoinTask<Long> task:invokeAll(tasks)){ //等待所有的子任务完成之后才会执行下一步循环操作。在任务被阻塞时,
                                                                                      //其他程序也可以去帮忙完成其他任务
                                                size += task.join();
     }
    }
   }
   return size;
  }
 }
 
 public static void main(final String[] args)
   throws InterruptedException,ExecutionException,TimeoutException{
  Scanner scanner = new Scanner(System.in);
  String str = scanner.next();
  System.out.println("get the output--->" + str);
  final long start = System.nanoTime();
  final long total = forkJoinPool.invoke(new FileSizeFinder(new File(str)));
  final long end = System.nanoTime();
  System.out.println("Total Size: " + total);
  System.out.println("Time taken: " + (end-start)/1.0e9);
 }
}

Fork-join API非常适合解决那些可以递归分解至小到足以顺序运行的问题。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/da4950327326c33eb9dc566f28861d71.html