JAVA递归思想实现全盘搜索文件系统之进阶版
转载自:https://tufeng.xyz/java/26.html(来源于:兔峰博客)
上一篇我们通过文章 JAVA递归思想实现全盘检索文件系统之基础版 了解到了全盘检索搜索文件系统所用到的核心思想——递归思想,
这一片文章所要讲解的实例将在上一篇基础上进行改进,主要借助多线程提升检索搜索文件系统的速度。
上一篇文章检索搜索文件系统的大体流程就是,先搜C盘,再搜D盘,再搜E盘。。。。我们可以看到,这样一个盘一个盘的搜下去,还是太慢了,
那么有没有办法多个盘符一起搜索呢,这样就能大大缩短检索文件的时间? 答案是可以的,这里我们主要借助多线程思想,为保证线程安全,
这里还将用到线程锁,小伙伴们还可以学习或者巩固一下关于线程方面的知识。
解析:
这里工具类相比上次多了一些全局变量,关于他们代表的含义请看下面实例代码中旁边的注释。
下面我来讲解一下globleSearchFile()函数关键部分:
这里遍历文件系统盘符,为每一个盘符开一个线程,线程里面调用searchFile()函数执行文件搜索,
多个线程同时运行,多个盘符同时进行搜索,效率大大提高
线程里面searchFile()函数执行完毕后对结果进行判断:
-
如果find为true,则表示找到目标文件,调用findFile()函数,将全局变量find赋值true,
由于所有线程里面在执行searchFile()函数时,开头都会做如下判断
if(find) {return false;}
这表示如果找到目标文件,则立即返回,不再查找
所以此时(找到目标文件)所有线程停止查找,立即执行结束
这样做的好处就是避免不必要的系统资源的消耗
-
如果find为false,则表示搜索完整个盘符后仍然没有找到目标文件,然后调用notFile()函数
search_num变量加一,当搜索完毕的盘数的数量达到最大值,即表示全盘搜索完毕,如下:
if(search_num==disk_num) { // 全盘搜索完毕,激活锁 synchronized (object) { over = true; object.notify(); } } // if search_num==disk_num
此时激活锁,返回全盘搜索结果,全盘搜索完毕。
实例代码如下,可以测试一下:
package m1;
import java.io.File;
public class Test {
String find_path = null; // 目标文件所在的路径(如果有的话)
Object object = new Object(); // 线程锁
volatile boolean find = false; // 目标文件是否找到
boolean over = false; //整个文件系统是否检索搜索完毕
Object object2 = new Object(); // 线程锁
int disk_num = 0; // 盘符数量
int search_num = 0; // 已搜索完毕的盘符数量
public void find_file() { // 找到文件后调用该函数,激活锁
synchronized (object) {
over = true;
find = true;
object.notify();
// System.out.println("find path="+dir_path);
}
}
public void not_findFile() { //搜索完盘符后没有找到目标文件,调用该函数
synchronized (object2) {
search_num++;
if(search_num==disk_num) { // 全盘搜索完毕,激活锁
synchronized (object) {
over = true;
object.notify();
}
} // if search_num==disk_num
}
}
// 搜索文件核心函数(递归函数)
public boolean searchFile(String dir_path,String des_fileName) {
if(find) {return false;}
File dir_file = new File(dir_path);
File[] files = dir_file.listFiles();
// if(dir_file.isFile()&&dir_file.getName().equals(des_fileName)) {find_file(dir_file.getAbsolutePath());}
if(files!=null) {
for(File file:files) {
if(file.isDirectory()) {
boolean exist = searchFile(file.getAbsolutePath(),des_fileName);
if(exist) {return true;}
else {continue;}
}
else {
// System.out.println("file: "+file.getAbsolutePath());
// if(file.getName().equals(des_fileName)) {return true;}
String file_name = file.getName();
if(file_name.equals(des_fileName)) {
find_path = file.getAbsolutePath();
return true;
}
} // if is file
} // for
}
return false;
} // list_files
//全盘搜索文件系统入口函数
public String globleSearchFile(String des_fileName) {
File[] roots = File.listRoots();
for(File file:roots) {
new Thread(new Runnable() {
// 遍历盘符,为每一个盘符开启一个线程,开始搜索目标函数
@Override
public void run() {
boolean find = searchFile(file.getAbsolutePath(), des_fileName);
if(find) {find_file();} //盘符搜索完毕后,对搜索结果进行判断处理
else {not_findFile();}
}
}).start();
} // for
synchronized (object) { //线程锁,如果搜索完毕,则释放锁,结束全盘搜索,返回搜索结果
while(!over) {
try {
object.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
// System.out.println("find? "+find);
return find_path;
}
public static void main(String[] args) {
long start_time = System.currentTimeMillis();
System.out.println("start find...");
Test searchFile = new Test();
String path = searchFile.globleSearchFile("wslk_strings.xml");
if(path!=null) {System.out.println("already find, file path :"+path);}
else {System.out.println("sorry,not find the file");}
System.out.println("用时:"+((System.currentTimeMillis()-start_time))+"毫秒");
// new SearchFile().new SearchThread("G:\\", "ToolTip.html").start();
}
}