采用多线程和生产者消费者模式来实现对于一个目录以及所有子目录下的文件内容的搜索,打印出包含指定关键字的行.

  利用ArrayBlockingQueue可以方便的实现生产者和消费者,所有消费者线程共用资源ArrayBlockingQueue对象,从而实现线程安全.生产者线程搜索当前目录及子目录,并且将相应的File对象添加到队列中,消费者线程对每个File对象进行关键字的查询,如果查到头,即停止查询.

  

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

/**
 * Created by Administrator on 2016/6/30.
 */
public class BlockingQueueTest {
    public static void main(String[] args) {
        Scanner in=new Scanner(System.in);
        System.out.print("Enter base directory:");
        String directory=in.nextLine();
        System.out.println("Enter key world.");
        String keyworld=in.nextLine();
        final int FILE_QUEUE_SIZE=10;   //队列的容积
        final int SEARCH_THREADS=100;   //消费者线程数目,(进行高并发的查询)
        BlockingQueue<File>queue=new ArrayBlockingQueue<>(FILE_QUEUE_SIZE);
        FileEnumerationTask enumerator=new FileEnumerationTask(queue,new File(directory));//生产者线程
        new Thread(enumerator).start();
        for (int i=1;i<SEARCH_THREADS;i++) {
            new Thread(new SearchTask(queue,keyworld)).start();//开启消费者线程
        }
    }
}
class FileEnumerationTask implements Runnable{
    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 (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void enumerate(File startingDirectory) {
        File[] files=startingDirectory.listFiles();
        for(File file:files) {
            if(file.isDirectory()) {
                enumerate(file);
            }
            else {
                try {
                    queue.put(file);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

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

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

    @Override
    public void run() {
        boolean done=false;
        while (!done) {
            try {
                File file=queue.take();     //线程安全的操作,取得File对象
                if(file==FileEnumerationTask.DUMMY) {
                    queue.put(file);
                    done=true;  //队列到头,不再查询
                }
                else
                    search(file);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private void search(File file) {
        try {
            try(Scanner in=new Scanner(file)) {
                int lineNumber=0;
                while(in.hasNextLine()) {
                    lineNumber++;
                    String line=in.nextLine();
                    if(line.contains(keyworld)) {
                        System.out.printf("%s:%d:%s:%n",file.getPath(),lineNumber,line);
                    }
                }
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}
原文地址:https://www.cnblogs.com/hlhdidi/p/5631314.html