zoukankan      html  css  js  c++  java
  • 用多线程写了个硬盘搜索功能,似乎也只比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() + "
    ");
                    ++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);
        }
    }
    

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

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

    追求吾之所爱
  • 相关阅读:
    SpringCloud--Ribbon--源码解析--Ribbon入口实现
    SpringCloud--Ribbon--使用demo
    装饰着模式(Decorator Pattern)
    SpringCloud--Eureka--配置
    SpringCloud--Eureka--原理及源码解析
    SpringCloud--Eureka--搭建
    观察者模式(Observer Pattern)
    策略模式(Strategy Pattern)
    xeus-clickhouse: Jupyter 的 ClickHouse 内核
    Spring的学习与实战(续)
  • 原文地址:https://www.cnblogs.com/rstz/p/14390958.html
Copyright © 2011-2022 走看看