如何使用阻塞隊列查詢文件內容中的關鍵字

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Scanner;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

/**
 * Created by Administrator on 2017/10/29 0029.
 * @author WXP
 * 使用阻塞隊列兩個顯著的好處就是:多線程操做共同的隊列時不須要額外的同步,
 * 另外就是隊列會自動平衡負載,即那邊(生產與消費兩邊)處理快了就會被阻塞掉,從而減小兩邊的處理速度差距。
 */
public class BlockingQueueTest {
  public static void main(String[] args){
      Scanner in = new Scanner(System.in);
      System.out.println("Enter base directory path: ");
      String directory = in.nextLine();
      System.out.print("Enter search keyword: ");
      String keyWord = in.nextLine();
      final int FILE_QUEUE_SIZE=10;//阻塞隊列大小
      final int SEARCH_THREADS=10;//關鍵字搜索線程個數
      //基於ArrayBlockingQueue的阻塞隊列
      BlockingQueue<File> queue = new ArrayBlockingQueue<File>(FILE_QUEUE_SIZE);
      //只啓動一個線程來搜索目錄
      FileEnumerationTask enumerator = new FileEnumerationTask(queue,new File(directory));
      new Thread(enumerator).start();
      //啓動100個線程用來在文件中搜索指定的關鍵字
      for (int i = 0; i < SEARCH_THREADS; i++) {
          new Thread(new SearchTask(queue,keyWord)).start();
      }
  }


}
class FileEnumerationTask implements Runnable{
    //DUMMY文件對象,放在阻塞隊列最後,用來標示文件已被遍歷完
    public static File DUMMY = new File("");
    private BlockingQueue<File> queue;
    private File startingDirectory;
    public FileEnumerationTask(BlockingQueue<File> queue, File startingDirectory) {
        this.queue = queue;
        this.startingDirectory = startingDirectory;
    }

    @Override
    public void run() {
          try {
              enumerate(startingDirectory);
              queue.put(DUMMY);//執行到這裏說明指定的目錄下文件已被遍歷完
          }catch (Exception e){
              e.printStackTrace();
          }
    }

    //將指定目錄下的全部文件File對象的放入阻塞隊列中
    public void enumerate(File directory)throws InterruptedException{
        File[] files = directory.listFiles();
        for (File file: files) {
            if(file.isDirectory()){
                enumerate(file);
            }else{
                //將元素放入隊尾,若是隊列滿則阻塞
                queue.put(file);
            }
        }
    }
}

class SearchTask implements Runnable{
    private BlockingQueue<File> queue;
    private String keyWord;

    public SearchTask(BlockingQueue<File> queue, String keyWord) {
      this.queue = queue;
      this.keyWord = keyWord;
    }

    @Override
    public void run() {
        try {
            boolean done = false;
            while (!done){
                //取出隊首元素,若是隊列爲空則阻塞
                File file = queue.take();
                if (file==FileEnumerationTask.DUMMY){
                     //取出來後從新放入,好讓其餘線程讀到它時也很快的結束
                    queue.put(file);
                    done=true;
                }else{
                   search(file);
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    public  void  search(File file)throws IOException{
        Scanner in = new Scanner(new FileInputStream(file));
        int lineNumber = 0;
        while (in.hasNextLine()){
            lineNumber++;
            String line = in.nextLine();
            //查詢相匹配的關鍵字
            if(line.contains(keyWord)){
                System.out.printf("%s:%d:%s%n",file.getPath(),lineNumber,line);
            }
        }
        in.close();
    }
}

注:僅供分享,內容參照其餘學者java

相關文章
相關標籤/搜索