3、异步执行任务
在ForkJoinPool中执行ForkJoinTask时,可以采用同步或者异步方式,当采用同步方式执行时,发送任务给Fork/Join线程池的方法直到
任务执行完成后才会返回结果。而采用异步的方式执行任务时,发送任务给执行器的方法将立即返回结果,但是任务仍能继续执行。
当采用同步的方式,ForkJoinPool类采用工作者窃取算法,采用异步的时候不能使用该算法。在本实例中只有调用join()
,或者get()方法来等待任务的结束时,ForkJoinPool类才使用工作者窃取算法。
本范例使用join方法等待任务的结束,然后获取它们的结果。也可以使用get方法的这两种重载方法来实现目标
1.get():如果ForkJoinTask类执行结束,或者一直等到结束,那么该方法则返回由compute()方法返回的结果。
2.get(long timeout,TimeUnit unit):如果任务还没有返回结果,则该方法将等待指定的时间。
如果超过了指定的时间,还没有返回结果,则该方法
返回null。
get()方法与join()方法的两个主要区别:
1.join()方法不能被中断,如果中断调用join()方法的线程,方法将抛出InterruptedException异常。
2.如果任务抛出任何运行时异常,则get()方法将返回ExecutionException异常,但是join()方法将返回RuntimeException异常。
/**
*
* @author fcs
* @date 2015-7-24
* 描述:使用异步的方式在一个文件夹及其子文件夹中来搜索带有指定扩展名的文件。
* 说明:
*/
public class FolderProcessor extends RecursiveTask<List<String>> {
private static final long serialVersionUID = -7846273985608315979L;
private String path;
private String extension;
public FolderProcessor(String path, String extension) {
this.path = path;
this.extension = extension;
}
@Override
protected List<String> compute() {
//存储文件夹中的名称
List<String> list = new ArrayList<String>();
//存储子任务,这些子任务将处理文件夹中的子文件夹
List<FolderProcessor> tasks = new ArrayList<FolderProcessor>();
File file = new File(path);
File content [] = file.listFiles();
if(content != null){
for (int i = 0; i < content.length; i++) {
if(content[i].isDirectory()){
FolderProcessor task = new FolderProcessor(content[i].getAbsolutePath(), extension);
//如果是子文件夹,使用该方法采用异步的方式执行
task.fork();
tasks.add(task);
}else{
if(checkFile(content[i].getName())){
list.add(content[i].getAbsolutePath());
}
}
}
}
if(tasks.size()> 50){
System.out.printf("%S: %d tasks ran.\n",file.getAbsolutePath(),tasks.size());
}
addResultsFromTasks(list, tasks);
return list;
}
//将通过这个任务而启动的子任务返回的结果增加到文件列表中,
//参数:字符串列表list, FolderProcessor子任务列表tasks
private void addResultsFromTasks(List<String> list,List<FolderProcessor> tasks){
for(FolderProcessor item: tasks){
list.addAll(item.join());
}
}
public boolean checkFile(String name){
return name.endsWith(extension);
}
}
package cn.fans.chapter5.three;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.TimeUnit;
//
public class Main {
public static void main(String[] args) {
ForkJoinPool pool = new ForkJoinPool();
//FolderProcessor system = new FolderProcessor("C:\\Windows","log");
//FolderProcessor apps = new FolderProcessor("C:\\Program Files","log");
FolderProcessor documents = new FolderProcessor("D:\\","log");
//pool.execute(system);
//pool.execute(apps);
pool.execute(documents);
do{
System.out.println("***********************************");
System.out.printf("Main: Paramllelism: %d\n",pool.getParallelism());
System.out.printf("Main: Active Thread: %d\n",pool.getActiveThreadCount());
System.out.printf("Main: Task Count: %d\n",pool.getQueuedTaskCount());
System.out.printf("Main: Steal Count: %d\n",pool.getStealCount());
System.out.println("***********************************");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}while((!documents.isDone()));
pool.shutdown();
List<String> results ;
results = documents.join();
System.out.printf("documents: %d files found.\n",results.size());
//System.out.printf("Apps: %d files found.\n",results.size());
//System.out.printf("Documents: %d files found.\n",results.size());
}
}
运行的部分截图: