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

Posted 大胡龙的小圈子

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了采用多线程和生产者消费者模式来实现对于一个目录以及所有子目录下的文件内容的搜索,打印出包含指定关键字的行.相关的知识,希望对你有一定的参考价值。

  利用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();
        }
    }
}

 

以上是关于采用多线程和生产者消费者模式来实现对于一个目录以及所有子目录下的文件内容的搜索,打印出包含指定关键字的行.的主要内容,如果未能解决你的问题,请参考以下文章

多线程之Condition的简介及原理解析

多线程:简易版本生产消费者模式纯语言概述

多线程生产者消费者模型

多线程:生产者/消费者模式

生产者/消费者模式(阻塞队列)

一、多线程下生产者消费者模式