当前位置:嗨网首页>书籍在线阅读

12-案例实现

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

案例实现

根据如下步骤来实现本案例。

1.创建一个名为 FolderProcessor 的类,并使之继承泛型类型为 ListCounted- Completer 类:

public class FolderProcessor extends
                        CountedCompleter<List<String>> {

2.声明一个名为 path 的私有 String 变量。该变量用于存储任务将要处理的文件夹全路径:

private String path;

3.声明一个名为 extension 的私有 String 变量。该变量用于存储任务要搜索的文件扩展名:

private String extension;

4.声明两个名为 tasksresultList 的私有 List 变量。第一个变量将存储任务中所有已启动的子任务,第二个变量则存储任务的执行结果:

private List<FolderProcessor> tasks;
private List<String> resultList;

5.实现该类的构造方法并初始化全部属性和其父类。将构造方法声明成 protected 类型,这样它只能在内部使用:

protected FolderProcessor (CountedCompleter<?> completer,
                           String path, String extension) {
  super(completer);
  this.path=path;
  this.extension=extension;
}

6.实现另一个公共构造方法来供外部调用。由于该方法创建的任务没有父任务,因此该实例对象不作为参数来传递:

public FolderProcessor (String path, String extension) {
  this.path=path;
  this.extension=extension;
}

7.实现 compute() 方法。因为任务的基类是 CountedCompleter 类,所以该方法返回值为空:

@Override
public void compute() {

8.初始化两个 List 变量:

resultList=new ArrayList<>();
tasks=new ArrayList<>();

9.获取文件夹的内容:

File file=new File(path);
File content[] = file.listFiles();

10.对于文件夹内的每一个元素,如果为子文件夹,则创建一个新的 FolderProcessor 实例对象,异步调用 fork() 方法来执行。使用第一个构造方法,传递当前任务作为已完成任务。同时调用 addToPendingCount() 方法,增加处理的任务数:

if (content != null) {
  for (int i = 0; i < content.length; i++) {
    if (content[i].isDirectory()) {
      FolderProcessor task=new FolderProcessor(this,
                      content[i].getAbsolutePath(), extension);
      task.fork();
      addToPendingCount(1);
      tasks.add(task);

11.否则,调用 checkFile() 方法对比当前文件和搜索文件的扩展名。若相同,则在之前声明的字符串列表中存储文件的全路径:

  } else {
    if (checkFile(content[i].getName())){
      resultList.add(content[i].getAbsolutePath());
    }
  }
}

12.如果 FolderProcessor 子任务列表元素超过50个,则打印信息来说明这一情况:

  if (tasks.size()>50) {
    System.out.printf("%s: %d tasks ran.\n",
                      file.getAbsolutePath(),tasks.size());
  }
}

13.调用 tryComplete() 方法来尝试结束当前任务:

  tryComplete();
}

14.实现 onCompletion()方 法。该方法在全部子任务运行结束后执行,它将所有子任务的运行结果汇总到当前任务的返回结果列表:

@Override
public void onCompletion(CountedCompleter<?> completer) {
  for (FolderProcessor childTask : tasks) {
    resultList.addAll(childTask.getResultList());
  }
}

15.实现 checkFile() 方法。该方法用于对比传递的文件参数和搜索的扩展名是否一致。若一致则返回 true ,否则返回 false

private boolean checkFile(String name) {
  return name.endsWith(extension);
}

16.实现 getResultList() 方法来返回一个任务列表。因为该方法的代码很简短,所以此处不再列出。

17.至此,我们可以开始实现应用程序的入口,创建包含 main() 方法的 Main 类:

public class Main {
  public static void main(String[] args) {

18.用默认构造方法创建 ForkJoinPool 实例对象:

ForkJoinPool pool=new ForkJoinPool();

19.创建3个 FolderProcessor 任务。初始化不同的文件夹路径:

FolderProcessor system=new FolderProcessor("C:\\Windows",
                                           "log");
FolderProcessor apps=new FolderProcessor("C:\\Program Files",
                                         "log");
FolderProcessor documents=new FolderProcessor("C:\\Documents
                                         And Settings","log");

20.在池中用 execute() 方法来执行这3个任务:

pool.execute(system);
pool.execute(apps);
pool.execute(documents);

21.在3个任务执行完成前,每隔1s在控制台打印一次池中状态信息:

  do {
    System.out.printf("**********************************
                       ********\n");
    System.out.printf("Main: Active Threads: %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.printf("**********************************
                       ********\n");
  try {
    TimeUnit.SECONDS.sleep(1);
  } catch (InterruptedException e) {
    e.printStackTrace();
  }
} while ((!system.isDone())||(!apps.isDone())||
         (!documents.isDone()));

22.调用 shutdown() 方法关闭 ForkJoinPool

pool.shutdown();

23.在控制台打印每个任务生成的结果数:

List<String> results;
results=system.join();
System.out.printf("System: %d files found.\n",results.size());
results=apps.join();
System.out.printf("Apps: %d files found.\n",results.size());
results=documents.join();
System.out.printf("Documents: %d files found.\n",
                   results.size());