用多线程写了个硬盘搜索功能,似乎也只比windows自带的快以点点。(方法不对嘛)

此时的我必然是刚起床!!!

最近学了多线程,想找个小的项目练练手。于是,利用多线程写了一个硬盘搜索功能。

具体实现是: 实现Runnable接口,使用线程池, 个别类使用单例模式。
Results.java : 存储搜索结果,运用了单例模式(懒汉式)。

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/**
 * @author xiaoxiao
 * @date 2021.1.30
 * */
public class Results {
    private Map<String, String> results; // 存储 文件名-绝对路径
    private static Results results0;

    private Results() {}
    public static Results getInstance() { // 单例模式
        if (results0 == null) results0 = new Results();
        return results0;
    }

    public boolean put(String fileName, String path) { // 向存储结构添加搜索结果
        if (this.results == null) {// 第一次添加,为result创建实例对象
            this.results = new HashMap<String, String>();
            this.results = Collections.synchronizedMap(this.results); // HashMap转换成安全的容器。
        }

        this.results.put(fileName, path); // 添加
        return true;
    }

    @Override
    public String toString() { // 输出搜索结果
        StringBuilder s = new StringBuilder("");
        int i = 1;
        if (results != null)
            for (Map.Entry<String, String> entry : this.results.entrySet()) {
                s.append(i + " : " + entry.getKey() + " 绝对路径: " + entry.getValue() + "\n");
                ++i;
            }
        else
            s.append("未找到该文件");
        return String.valueOf(s); // 将StringBuilder转换成String
    }
}

SearchFiles.java : 实现搜索功能

import java.io.File;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * @author xiaoxiao
 * @date 2021.1.30
 * */

public class SearchFiles implements Runnable {
    private File beginPath; // 开始路径
    private String target; // 目标文件
    private Results results; // 保存搜索结果
    private ConcurrentLinkedQueue<File> directories;

    private SearchFiles() { 
        this.directories = new ConcurrentLinkedQueue<File>();
        this.results = Results.getInstance();
    }

    public SearchFiles(String target) { // 默认从C盘中搜索
        this();
        this.target = target; // 目标文件
        this.beginPath = new File("C:/");
        this.directories.add(this.beginPath);
    }

    public SearchFiles(String beginPath, String target) { // 传入指定搜索路径
        this();
        this.target = target;
        this.beginPath = new File(beginPath); // 指定路径搜索
        this.directories.add(this.beginPath);
    }

// 递归搜索

//    public void search(File file) {
//        if (file.isFile()) {
//            if (file.getName().contains(target)) {
//                results.put(file.getName(), file.getAbsolutePath());
//            }
//            return;
//        }
//        String[] list = file.list();
//        if (list == null)  return;
//        for (int i = 0; i < list.length; i++) {
//            search(new File(file, list[i]));
//        }
//    }

    private boolean flag;
    @Override
    public void run() {
        while (true) {
            File file = this.directories.poll();
            // 当出现第一个线程进入,会把里面的唯一的元素拿出,此时队列为空,poll() 返回的就是空,会出现空指针异常,这里就是在没有数据时,让其一直循环。
            if (file == null) // 避免其他线程中断
                continue;

            File[] files = file.listFiles();
            if (files != null)
                for (File file1 : files) {
                    if (file1.getName().contains(target))
                    	// 如果不想搜索完后输出,可以将保存结果注释掉,并用输出文件名和路径
                        this.results.put(file1.getName(), file1.getAbsolutePath());
//                        System.out.println(file1.getName() + " : " + file1.getAbsolutePath());;
					// 判断是否时文件夹,是否有读写权限
                    if (file1.isDirectory() && file1.canRead() && file1.canWrite())
                        this.directories.add(file1);
                }
            // 在这里判断
            if (this.directories.size() == 0)
                break;

        }


    }

    @Override
    public String toString() {
        return results.toString();
    }


}

Main.java : 程序运行

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
 * @author xiaoxiao
 * @date 2021.1.30
 * */
public class Main {
    public static void main(String[] args) {
        long t = System.currentTimeMillis();
        SearchFiles searchFiles = new SearchFiles("D:/",".md");
//       searchFiles.search(searchFiles.getBeginPath()); // 这个是递归方式, 单线程。

        ExecutorService service = Executors.newFixedThreadPool(9); // 声明线程池,大小为9
        for (int i = 0; i < 9; ++ i) { //
            service.execute(searchFiles);
        }

        service.shutdown();

        try { // 等待线程池里的线程执行完,在执行主线程。
            service.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long e = System.currentTimeMillis();
        System.out.println(e - t);
        System.out.println(searchFiles);
    }
}

效果图
在这里插入图片描述

如果不正确的地方,请大家指出,谢谢!

posted @ 2021-01-30 14:08  ACWink  阅读(98)  评论(0编辑  收藏  举报