简介
- Callable
Callable是类似Runnable的类,主要区别在于Callable是可以返回结果,而Runnable不会。
- FutureTask
简单说FutureTask的作用是可以启用、取消、并且判断线程是否完成,可以搭配Callable和Runnable使用。和Callable一起使用时,可以实现在线程完成任务后获取返回结果。
应用
众所周知,为什么要使用多线程,无非是为了加快任务的处理速度。比如现在需要你计算某个目录下的文件数量,你可以选择单线程遍历统计,也可以考虑使用多线程遍历查询。
public class FileCountCallableTest {
public static void main(String[] args){
//填写你想统计的文件夹目录
File root = new File("D:\\");
countByConcurrent(root);
countBySingle(root);
}
/**
* 多线程计算文件数量
*
* 获取目标目录下的子目录,并把每个子目录生成新线程任务达到加快计算目的
*
* @param targetDir
*/
static void countByConcurrent(File targetDir){
try {
long t1 = System.currentTimeMillis();
File[] files = targetDir.listFiles();
ExecutorService es = Executors.newFixedThreadPool(4);
List<FutureTask> futureTaskList = new ArrayList<FutureTask>();
int sumCount = 0;
for(File file:files){
if(file.isDirectory()){
//每个目录生成新线程任务
FileCountCallable fileCountCallable = new FileCountCallable(file.getPath());
FutureTask<Integer> futureTask = new FutureTask(fileCountCallable);
es.submit(futureTask);
futureTaskList.add(futureTask);
}else{
sumCount++;
}
}
//把每个任务的计算结果相加,得出最终结果
for(FutureTask<Integer> futureTask:futureTaskList){
sumCount += futureTask.get();
}
es.shutdown();
System.out.println("sumCount:"+sumCount);
System.out.println("countByConcurrent finish takes:"+(System.currentTimeMillis() - t1));
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 单线程计算文件数量
*
* @param targetDir
*/
static void countBySingle(File targetDir){
try {
long t1 = System.currentTimeMillis();
int sumCount = FileHelper.searchFiles(targetDir);
System.out.println("sumCount:"+sumCount);
System.out.println("countBySingle finish takes:"+(System.currentTimeMillis() - t1));
}catch (Exception e){
e.printStackTrace();
}
}
}
public class FileCountCallable implements Callable<Integer>{
private File root;
public Integer call() {
long t1 = System.currentTimeMillis();
int count = FileHelper.searchFiles(root);
return count;
}
public FileCountCallable(String pathName) {
root = new File(pathName);
}
}
代码比较简单,比如一个目录下有x、y、z三个文件夹,我可以一个线程去遍历计算,也可以启用3个线程分别去计算,最终把3个线程的结果相加就是最终结果。
最终我在本机上测试的结果:
sumCount:155963
countByConcurrent finish takes:7793 ms
sumCount:155963
countBySingle finish takes:9608 ms
采用多线程任务的方式,节省了18.9%的时间,相差并不是很大,主要是因为我的文件分布不均匀,采取以上策略时有的任务工作量大、有的很小,如果是分布比较均匀的话节省时间可以达到50%。当然要根据实际的需求调整多任务的策略,尽量使每个任务的工作量相差并不大。
还有在我们实际项目中可以使用的场景:
- http请求:比如某个功能,需要你去5个api去获取数据。
- 文件处理: 比如图片压缩、水印
- 数据库:多个sql查询
最后祝大家早日發財
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。