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