package thread.bolckqueue;
import java.io.File;
import java.util.Scanner;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class TestOne {
private static final int FILE_QUENE_SIZE = 1;
private static final int SEARCH_THREADS = 100;
private static final File DUMMY= new File("");
private static final BlockingQueue<File> queue = new ArrayBlockingQueue<>(FILE_QUENE_SIZE);
public static void main(String[] args) {
// TODO Auto-generated method stub
//阻塞队列
//使用队列可以安全从一个线程向另一个线程传递数据,操作的是队列而不是对象
//队列已满,向其中添加线程,获取移除空队列的时候会阻塞。
//队列会平衡负载,第一个线程集运行的比第二个慢,第二个线程集在等待结果时会堵塞,或者第一个线程集运行的比较快,会等待第二个线程集赶上来
/**
*
* 阻塞队列方法分为以下 3类, 这取决于当队列满或空时它们的响应方式。
* 如果将队列当 作线程管理工具来使用, 将要用到 put 和 take 方法。
* 当试图向满的队列中添加或从空的队列 中移出元素时,add、 remove 和 element 操作抛出异常。
* 当然,在一个多线程程序中, 队列会 在任何时候空或满, 因此,一定要使用 offer、poll 和 peek方法作为替代。
* 这些方法如果不能 完成任务,只是给出一个错误提示而不会抛出异常
*
*
*
* put 添加一个元素,如果队列满则阻塞
*
* take 移除并返回头元素 ,如果队列已满则会堵塞
*
*/
/**
* 查找文件夹下的多个文件,打印包含keyword的文件
*/
try (Scanner in = new Scanner(System.in)){
System.out.print("Enter base directory (e.g. /opt/jdk1.8.0/src):");
String directory = in.nextLine();
System.out.print("Enter keyword (e.g.volatile): ");
String keyword = in.nextLine();
Runnable en = () ->{
try {
enumerate(new File(directory));
queue.put(DUMMY);
} catch (InterruptedException e) {
e.printStackTrace();
}
};
new Thread(en).start();
for (int i = 0; i < SEARCH_THREADS; i++) {
Runnable searcher = () -> {
try {
boolean done = false;
while (!done) {
File file = queue.take();
if (file == DUMMY) {
queue.put(file);
done = true;
}else {
search(file, keyword);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
};
new Thread(searcher).start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void enumerate(File directory){
try {
File[] files = directory.listFiles();
for (File file : files) {
if (file.isDirectory()) {
enumerate(file);
} else {
queue.put(file);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void search(File file ,String keyword){
try (Scanner in = new Scanner(file,"UTF-8")){
int lineNumber = 0;
while(in.hasNextLine()){
lineNumber++;
String line = in.nextLine();
if (line.contains(keyword)) {
System.out.printf("%s;%d%n",file.getPath(),lineNumber,line);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}