1.单线程递归获取文件夹大小
public static long getDirSize(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 += getDirSize(child);
return total;
}
2.多线程BlockingQueue
import java.io.File;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
/**
* Created by shijack on 2016/7/8.
* <p>Attention: when the dir size is larger than 1G the speed can faster than in only one thread!</p>
*/
public class ConcurrentDirSizeCountUtil {
private ExecutorService service;
final private BlockingQueue<Long> fileSizes = new ArrayBlockingQueue<Long>(
500);
final AtomicLong pendingFileVisits = new AtomicLong();
private void startExploreDir(final File file) {
pendingFileVisits.incrementAndGet();
service.execute(new Runnable() {
public void run() {
exploreDir(file);
}
});
}
private void exploreDir(final File file) {
long fileSize = 0;
if (file.isFile())
fileSize = file.length();
else {
final File[] children = file.listFiles();
if (children != null)
for (final File child : children) {
if (child.isFile())
fileSize += child.length();
else {
startExploreDir(child);
}
}
}
try {
fileSizes.put(fileSize);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
pendingFileVisits.decrementAndGet();
}
public long getTotalSizeOfFile(final String fileName) throws InterruptedException {
service = Executors.newFixedThreadPool(100);
try {
startExploreDir(new File(fileName));
long totalSize = 0;
while (pendingFileVisits.get() > 0 || fileSizes.size() > 0) {
final Long size = fileSizes.poll(10, TimeUnit.SECONDS);
totalSize += size;
}
return totalSize;
} finally {
service.shutdown();
}
}
}
3.多线程Build.VERSION_CODES.LOLLIPOP之后使用ForkJoinTask
import android.annotation.TargetApi;
import android.os.Build;
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;
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
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);
}
}
注意:
在文件夹的大小为200M(此为大概数,不准确)以下的时候,多线程反而可能比递归更费时,请谨慎选择。