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.实现该类的构造器。它有两个参数:一个是类型为 Runnable 的 runnable 对象,另一个是类型为 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.如果该方法的参数 v 是 null ,则将 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();
}