1. 程式人生 > 其它 >用多執行緒寫了個硬碟搜尋功能,似乎也只比windows自帶的快以點點。(方法不對嘛)

用多執行緒寫了個硬碟搜尋功能,似乎也只比windows自帶的快以點點。(方法不對嘛)

技術標籤:java高階多執行緒java

此時的我必然是剛起床!!!

最近學了多執行緒,想找個小的專案練練手。於是,利用多執行緒寫了一個硬碟搜尋功能。

具體實現是: 實現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);
    }
}

效果圖
在這裡插入圖片描述

如果不正確的地方,請大家指出,謝謝!