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

04-案例实现

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

案例实现

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

1.创建 FileSearch 类并实现 Runnable 接口。该类将实现文件搜索操作:

public class FileSearch implements Runnable {

2.声明两个私有的字符串属性:一个命名为 initPath ,它用于存储搜索操作的初始文件夹;另一个命名为 end ,它用于存储待搜索文件的扩展名:

private String initPath;
private String end;

3.声明一个私有的 List 属性,将其命名为 results ,用来存储已发现文件的完整路径:

private List<String> results;

4.实现类的构造器并初始化这些属性:

public FileSearch(String initPath, String end) {
  this.initPath = initPath;
  this.end = end;
  results=new ArrayList<>();
}

5.实现 getResults() 方法。该方法用于返回已发现文件的完整路径:

public List<String> getResults() {
  return results;
}

6.实现 run() 方法。首先向控制台写一条信息,表明任务开始了:

@Override
public void run() {
  System.out.printf("%s: Starting\n",
                    Thread.currentThread().getName());

7.如果 initPath 是一个文件夹的路径,则调用 directoryProcess() 方法处理它的文件和子文件夹:

File file = new File(initPath);
  if (file.isDirectory()) {
    directoryProcess(file);
  }

8.实现辅助方法 directoryProcess() ,它接收一个 File 对象作为参数。首先,获取该参数指向的文件夹中的内容:

private void directoryProcess(File file) {
  File list[] = file.listFiles();

9.如果文件夹的子元素还是文件夹,则递归调用 directoryProcess() 方法;如果是文件则调用 fileProcess() 方法:

if (list != null) {
  for (int i = 0; i < list.length; i++) {
    if (list[i].isDirectory()) {
      directoryProcess(list[i]);
    } else {
      fileProcess(list[i]);
    }
  }
}

10.实现辅助方法 fileProcess() ,它接收一个带有完整文件路径的 File 对象。它会检查文件的扩展名是否和 end 属性相等,如果相等就把文件的完整路径添加到 results 中:

private void fileProcess(File file) {
  if (file.getName().endsWith(end)) {
    results.add(file.getAbsolutePath());
  }
}

11.实现 Task 类并扩展 FutureTask 。使用 List<String> 作为泛型,它就是任务返回值的类型:

public class Task extends FutureTask<List<String>> {

12.声明一个私有的 FileSearch 属性,并命名为 fileSearch

private FileSearch fileSearch;

13.实现该类的构造器。它有两个参数:一个是类型为 Runnablerunnable 对象,另一个是类型为 List<String>result 对象。在构造器中要以相同的参数调用父类构造器,然后将 runnable 对象转换为 FileSearch 类型,并赋值给 FileSearch 属性:

public Task(Runnable runnable, List<String> result) {
  super(runnable, result);
  this.fileSearch=(FileSearch)runnable;
}

14.覆盖 FutureTask 类的 set() 方法:

@Override
protected void set(List<String> v) {

15.如果该方法的参数 vnull ,则将 FileSearch 类的 getResults() 方法的返回值赋值给 v

v=fileSearch.getResults();

16.然后调用父类方法,传入该参数:

super.set(v);

17.最后实现案例主类。创建 Main 并添加 main() 方法:

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

18.调用 Executors 类的 newCachedThreadPool() 方法,创建一个名为executor的 ThreadPoolExecutor 对象:

ExecutorService executor = Executors.newCachedThreadPool();

19.用不同的初始文件夹创建3个 FileSearch 对象,寻找扩展名为 log 的文件:

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

20.创建3个在执行器中执行搜索操作的 Task 对象:

Task systemTask=new Task(system,null);
Task appsTask=new Task(apps,null);
Task documentsTask=new Task(documents,null);

21.调用 submit() 方法将这些对象发送给执行器对象。该版本的 submit() 方法返回一个 Future<?> 对象,不过不用管它,我们用 FutureTask 的子类来控制任务:

executor.submit(systemTask);
executor.submit(appsTask);
executor.submit(documentsTask);

22.调用执行器对象的 shutdown() 方法,使其在这3个任务完成时结束执行:

executor.shutdown();

23.调用执行器对象的 awaitTermination() 方法,为其指定长时间的等待,确保它在这3个任务结束前不会返回:

try {
  executor.awaitTermination(1, TimeUnit.DAYS);
} catch (InterruptedException e) {
  e.printStackTrace();
}

24.用 Task 对象的 get() 方法获取每个任务的结果列表,然后打印列表的大小信息:

try {
  System.out.printf("Main: System Task: Number of Results: %d\n",
                    systemTask.get().size());
  System.out.printf("Main: App Task: Number of Results: %d\n",
                    appsTask.get().size());
  System.out.printf("Main: Documents Task: Number of
                     Results: %d\n",documentsTask.get().size());
} catch (InterruptedException e) {
  e.printStackTrace();
} catch (ExecutionException e) {
  e.printStackTrace();
}