81,092
社区成员
发帖
与我相关
我的任务
分享
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;
/**
* 使用阻塞队列查找文件夹文件中的关键字
* 对于实际变成来说,应该尽可以远离底层结构,使用游并发处理的专业人士实现的较高层次的结构要方便的多,要安全的多(这算不算在给sun广告?)
* 在协调多个线程之间的合作,阻塞队列是一个有用的工具。工作者线程可以周期性的将中间结果存储在阻塞队列中。其他的工作者线程移除中间结果并进一步加以修改
* @author Administrator
*
*/
public class BlockigQueueTest {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("Enter base directory(e.g /usr/local/jdk1.6.0/src):");
//得到输入的文件夹
String directory= in.nextLine();
System.out.println("Enter keyword(e.g volatile):");
//得到输入的关键字
String keyword = in.nextLine();
final int FILE_QUEUE_SIZE = 10;
//使用100条线程进行搜索
final int SEARCH_THREAD = 100;
/**
* ArrayBlockingQueue 在构造时需要指定容量,并且有一个可选的参数来指定是否需要公平性
* 该队列使用循环数组实现
*
* 这是ArrayBlockingQueue的部分源码 可以看到他们实际上已经实现了锁机制
* public ArrayBlockingQueue(int capacity, boolean fair) {
if (capacity <= 0)
throw new IllegalArgumentException();
this.items = (E[]) new Object[capacity];
lock = new ReentrantLock(fair);
notEmpty = lock.newCondition();
notFull = lock.newCondition();
}
这里还可以用
LinkedBlockQueue():构造一个无上限的队列或双向队列 用链表实现
LinkedBlockQueue(int 容量):构造一个有上限的队列或双向队列 用链表实现
或者使用
PriorityBlockingQueue():构造一个无边界的阻塞优先队列,用堆实现
详细大家可以看下API
本程序在这里用来遍历和查找,所以用ArrayBlockingQueue
*/
BlockingQueue<File> queue = new ArrayBlockingQueue<File>(FILE_QUEUE_SIZE);
FileEnmerationTask enumerator = new FileEnmerationTask(queue,new File(directory));
//启动执行枚举文件夹文件的线程,将文件夹内的文件放入到阻塞队列中
new Thread(enumerator).start();
for(int i=1;i<SEARCH_THREAD;i++){//启动100个线程进行搜索
new Thread(new SearchTask(queue, keyword)).start();
}
}
}
class FileEnmerationTask implements Runnable{
/**
* 初始化队列和开始查找的文件夹
* @param queue
* @param startDirectory
*/
public FileEnmerationTask(BlockingQueue<File> queue,File startDirectory){
this.queue = queue;
this.startingDirectory = startDirectory;
}
@Override
public void run() {
try {
//枚举文件并放入阻塞队列中
ennmerat(startingDirectory);
//放入一个空的来避免 队列为空 使用take函数造成阻塞
queue.put(DUMY);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void ennmerat(File directory) throws InterruptedException{
File[] files = directory.listFiles();
for(File file:files){
if(file.isDirectory()){//如果是文件夹 则迭代
ennmerat(file);
}else{//如果是文件 直接放入阻塞队列
queue.put(file);
}
}
}
public static File DUMY = new File("");
private BlockingQueue<File> queue;
private File startingDirectory;
}
class SearchTask implements Runnable{
public SearchTask(BlockingQueue<File> queue,String keyword){
this.queue = queue;
this.keyword = keyword;
}
@Override
public void run() {
// TODO Auto-generated method stub
try {
boolean done = false;
while(!done){
// take 移出并返回头元素 如果队列中 则阻塞,所以 需要用queue.put(DUMY);
File file = queue.take();
if(file == FileEnmerationTask.DUMY){
queue.put(file);
done= true;
}else{
search(file);
}
}
}catch(IOException e){
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 查找关键字
* @param file 目前文件
* @throws IOException
*/
private void search(File file) throws IOException{
// TODO Auto-generated method stub
Scanner in = new Scanner(new FileInputStream(file));
int lineNumber =0 ;
while(in.hasNext()){
lineNumber++;
String line = in.nextLine();
if(line.contains(keyword)){
//打印查询信息
System.out.printf("%s:%d:%s%n",file.getPath(),lineNumber,line);
}
}
in.close();
}
private BlockingQueue<File> queue;
private String keyword;
}