场景为,给到一个硬盘上文件或文件夹,(当然文件夹时,多线程的优势才能越发体现出来),得到该文件或文件夹的大小和计算该结果所需要的时间。
首先是单线程下的例子,这个可难不倒大家,代码如下:
public class TotalFileSizeSequential {
private long getTotalSizeOfFilesInDir(final File file) {
if (file.isFile()) return file.length();
final File[] children = file.listFiles();
long total = 0;
if (children != null)
for(final File child : children)
total += getTotalSizeOfFilesInDir(child);
return total;
}
public static void main(final String[] args) {
final long start = System.nanoTime();
final long total = new TotalFileSizeSequential()
.getTotalSizeOfFilesInDir(new File("D:/idea_ws"));
final long end = System.nanoTime();
System.out.println("Total Size: " + total);
System.out.println("Time taken: " + (end - start)/1.0e9);
}
}
上述代码在我的机器上(win7,8g,i5)多次运行后的均值为:文件夹大小为276590351字节,即263M;耗时大概 0.25s
Total Size: 276589881
Time taken: 0.258706999
至此,我们当然希望通过多线程扫描计算的方式,来更快的得到这个文件夹的大小,于是有个这个看似设计不错的,native版的代码:
public class NaivelyConcurrentTotalFileSize {
private long getTotalSizeOfFilesInDir(
final ExecutorService service, final File file)
throws InterruptedException, ExecutionException, TimeoutException {
if (file.isFile()) return file.length();
long total = 0;
final File[] children = file.listFiles();
if (children != null) {
final List> partialTotalFutures =
new ArrayList>();
for(final File child : children) {
partialTotalFutures.add(service.submit(new Callable() {
public Long call() throws InterruptedException,
ExecutionException, TimeoutException {
return getTotalSizeOfFilesInDir(service, child);
}
}));
}
for(final Future partialTotalFuture : partialTotalFutures)
total += partialTotalFuture.get(100, TimeUnit.SECONDS);
}
return total;
}
private long getTotalSizeOfFile(final String fileName)
throws InterruptedException, ExecutionException, TimeoutException {
final ExecutorService service = Executors.newFixedThreadPool(100);
try {
return getTotalSizeOfFilesInDir(service, new File(fileName));
} finally {
service.shutdown();
}
}
public s