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();
}