javafifo
‘壹’ java中的集合有几种
集合类是放在java.util.*;这个包里。集合类存放的都是对象的引用,而非对象本身,为了说起来方便些,我们称集合中的对象就是指集合中对象的引用(reference)。引用的概念大家不会忘了吧,在前边我们讲数据类型时讲的。
集合类型主要有3种:set(集)、list(列表)、map(映射)和Queue(队列)。//队列为jdk5中的加上的
(1) Set
集(set)是最简单的一种集合,它的对象不按特定方式排序,只是简单的把对象加入集合中,就像往口袋里放东西。对集中成员的访问和操作是通过集中对象的引用进行的,所以集中不能有重复对象。我们知道数学上的集合也是Set这个,集合里面一定是没有重复的元素的。
(2)List
列表(List)的主要特征是其对象以线性方式存储,没有特定顺序,只有一个开头和一个结尾,当然,它与根本没有顺序的Set是不同的。它是链表嘛,一条链肯定有顺序这个顺序就不一定了。
(3)Map
映射(Map),这个在java里不是地图的意思,其实地图也是映射哈。它里面的东西是键-值对(key-value)出现的,键值对是什么呢?举个例子,比如我们查字典,用部首查字法。目录那个字就是键,这个字的解释就是值。键和值成对出现。这样说可以理解吧。这也是很常用的数据结构哦。
(4)Queue
在jdk5.0以前,通常的实现方式是使用java.util.List集合来模仿Queue。Queue的概念通过把对象添加(称为enqueuing的操作)到List的尾部(即Queue的后部)并通过从List的头部(即Queue的前部)提取对象而从 List中移除(称为dequeuing的操作)来模拟。你需要执行先进先出的动作时可以直接使用Queue接口就可以了。
这4个东西,有时候功能还不太完善,需要有些子类继承它的特性。Set的子接口有TreeSet,SortedSet,List的有ArrayList等,Map里有HashMap,HashTable等,Queue里面有BlockingQueue等。我们来看看例子吧:
实践: Set举例
import java.util.*;
public class SetExample {
public static void main(String[] args) {
Set set = new HashSet(); //HashSet是Set的子接口
set.add("one");
set.add("second");
set.add("3rd");
set.add(new Integer(4));
set.add(new Float( 5.0F ));
set.add("second");
set.add(new Integer(4));
System.out.println(set);
}}
List举例:
import java.util.*;
public class ListExample {
public static void main(String[] args) {
List list = new ArrayList();
list.add("one");
list.add("second");
list.add("3rd");
list.add(new Integer(4));
list.add(new Float( 5.0F ));
list.add("second");
list.add(new Integer(4));
System.out.println(list);
}}
Map举例
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
import java.io.FileReader;
public class MapExample {
public static void main(String[] args) throws java.io.FileNotFoundException {
Map word_count_map = new HashMap();
FileReader reader = new FileReader(args[0]);
Iterator words = new WordStreamIterator(reader);
while ( words.hasNext() ) {
String word = (String) words.next();
String word_lowercase = word.toLowerCase();
Integer frequency = (Integer)word_count_map.get(word_lowercase);
if ( frequency == null ) {
frequency = new Integer(1);
} else {
int value = frequency.intValue();
frequency = new Integer(value + 1);}
word_count_map.put(word_lowercase, frequency);
}
System.out.println(word_count_map);
}}
Queue举例:
import java.io.IOException;
import java.io.PrintStream;
import java.util.LinkedList;
import java.util.Queue;
public class QueueTester {
public Queue<String> q; //发现了一个奇怪的语法,这个尖括号是泛型声明
public QueueTester() {q = new LinkedList<String>();}
public void testFIFO(PrintStream out) throws IOException {
q.add("First");
q.add("Second");
q.add("Third");
Object o;
while ((o = q.poll()) != null) {
out.println(o);}}
public static void main(String[] args) {
QueueTester tester = new QueueTester();
try { tester.testFIFO(System.out);
} catch (IOException e) {
e.printStackTrace(); } }}
‘贰’ 如何用java实现fifo页面置换算法
[fifo.rar] - 操作系统中内存页面的先进先出的替换算法fifo
[先进先出页面算法程序.rar] - 分别实现最佳置换算法(optimal)、先进先出(fifo)页面置换算法和最近最久未使用(LRU)置换算法,并给出各算法缺页次数和缺页率。
[0022.rar] - 模拟分页式虚拟存储管理中硬件的地址转换和缺页中断,以及选择页面调度算法处理缺页中断
[Change.rar] - 用java实现操作系统的页面置换 其中包括 最佳置换算法(Optimal)、先进先出算法(First-in, First-out) 、最近最久不用的页面置换算法(LeastRecently Used Replacement)三种算法的实现
[M_Management.rar] - 操作系统中内存管理页面置换算法的模拟程序,采用的是LRU置换算法
[detail_of_44b0x_TCPIP.rar] - TCPIP 程序包加载到44b0x 的ADS1.2工程文件的说明书。说名了加载过程的细节和如何处理演示程序和代码。演示代码已经上传,大家可以搜索
[.rar] - java操作系统页面置换算法: (1)进先出的算法(fifo) (2)最近最少使用的算法(LRU) (3)最佳淘汰算法(OPT) (4)最少访问页面算法(LFU) (注:由本人改成改进型Clock算法) (5)最近最不经常使用算法(NUR)
‘叁’ java如何实现进程间的通信
传统的进程间通信的方式有大致如下几种:
(1) 管道(PIPE)
(2) 命名管道(FIFO)
(3) 信号量(Semphore)
(4) 消息队列(MessageQueue)
(5) 共享内存(SharedMemory)
(6) Socket
Java如何支持进程间通信。我们把Java进程理解为JVM进程。很明显,传统的这些大部分技术是无法被我们的应用程序利用了(这些进程间通信都是靠系统调用来实现的)。但是Java也有很多方法可以进行进程间通信的。
除了上面提到的Socket之外,当然首选的IPC可以使用Rmi,或者Corba也可以。另外Java nio的MappedByteBuffer也可以通过内存映射文件来实现进程间通信(共享内存)。
‘肆’ java 中 阻塞队列 非阻塞队列 和普通队列的区别是什么
阻塞队列与普通队列的区别在于,当队列是空的时,从队列中获取元素的操作将会被阻塞,或者当队列是满时,往队列里添加元素的操作会被阻塞。试图从空的阻塞队列中获取元素的线程将会被阻塞,直到其他的线程往空的队列插入新的元素。同样,试图往已满的阻塞队列中添加新元素的线程同样也会被阻塞,直到其他的线程使队列重新变得空闲起来,如从队列中移除一个或者多个元素,或者完全清空队列.
1.ArrayDeque, (数组双端队列)
2.PriorityQueue, (优先级队列)
3.ConcurrentLinkedQueue, (基于链表的并发队列)
4.DelayQueue, (延期阻塞队列)(阻塞队列实现了BlockingQueue接口)
5.ArrayBlockingQueue, (基于数组的并发阻塞队列)
6.LinkedBlockingQueue, (基于链表的FIFO阻塞队列)
7.LinkedBlockingDeque, (基于链表的FIFO双端阻塞队列)
8.PriorityBlockingQueue, (带优先级的无界阻塞队列)
9.SynchronousQueue (并发同步阻塞队列)
阻塞队列和生产者-消费者模式
阻塞队列(Blocking queue)提供了可阻塞的put和take方法,它们与可定时的offer和poll是等价的。如果Queue已经满了,put方法会被阻塞直到有空间可用;如果Queue是空的,那么take方法会被阻塞,直到有元素可用。Queue的长度可以有限,也可以无限;无限的Queue永远不会充满,所以它的put方法永远不会阻塞。
阻塞队列支持生产者-消费者设计模式。一个生产者-消费者设计分离了“生产产品”和“消费产品”。该模式不会发现一个工作便立即处理,而是把工作置于一个任务(“to do”)清单中,以备后期处理。生产者-消费者模式简化了开发,因为它解除了生产者和消费者之间相互依赖的代码。生产者和消费者以不同的或者变化的速度生产和消费数据,生产者-消费者模式将这些活动解耦,因而简化了工作负荷的管理。
生产者-消费者设计是围绕阻塞队列展开的,生产者把数据放入队列,并使数据可用,当消费者为适当的行为做准备时会从队列中获取数据。生产者不需要知道消费者的省份或者数量,甚至根本没有消费者—它们只负责把数据放入队列。类似地,消费者也不需要知道生产者是谁,以及是谁给它们安排的工作。BlockingQueue可以使用任意数量的生产者和消费者,从而简化了生产者-消费者设计的实现。最常见的生产者-消费者设计是将线程池与工作队列相结合。
阻塞队列简化了消费者的编码,因为take会保持阻塞直到可用数据出现。如果生产者不能足够快地产生工作,让消费者忙碌起来,那么消费者只能一直等待,直到有工作可做。同时,put方法的阻塞特性也大大地简化了生产者的编码;如果使用一个有界队列,那么当队列充满的时候,生产者就会阻塞,暂不能生成更多的工作,从而给消费者时间来赶进进度。
有界队列是强大的资源管理工具,用来建立可靠的应用程序:它们遏制那些可以产生过多工作量、具有威胁的活动,从而让你的程序在面对超负荷工作时更加健壮。
虽然生产者-消费者模式可以把生产者和消费者的代码相互解耦合,但是它们的行为还是间接地通过共享队列耦合在一起了
类库中包含一些BlockingQueue的实现,其中LinkedBlockingQueue和ArrayBlockingQueue是FIFO队列,与 LinkedList和ArrayList相似,但是却拥有比同步List更好的并发性能。PriorityBlockingQueue是一个按优先级顺序排序的队列,当你不希望按照FIFO的属性处理元素时,这个PriorityBolckingQueue是非常有用的。正如其他排序的容器一样,PriorityBlockingQueue可以比较元素本身的自然顺序(如果它们实现了Comparable),也可以使用一个 Comparator进行排序。
最后一个BlockingQueue的实现是SynchronousQueue,它根本上不是一个真正的队列,因为它不会为队列元素维护任何存储空间。不过,它维护一个排队的线程清单,这些线程等待把元素加入(enqueue)队列或者移出(dequeue)队列。因为SynchronousQueue没有存储能力,所以除非另一个线程已经准备好参与移交工作,否则put和take会一直阻止。SynchronousQueue这类队列只有在消费者充足的时候比较合适,它们总能为下一个任务作好准备。
非阻塞算法
基于锁的算法会带来一些活跃度失败的风险。如果线程在持有锁的时候因为阻塞I/O,页面错误,或其他原因发生延迟,很可能所有的线程都不能前进了。
一个线程的失败或挂起不应该影响其他线程的失败或挂起,这样的算法成为非阻塞(nonblocking)算法;如果算法的每一个步骤中都有一些线程能够继续执行,那么这样的算法称为锁自由(lock-free)算法。在线程间使用CAS进行协调,这样的算法如果能构建正确的话,它既是非阻塞的,又是锁自由的。非竞争的CAS总是能够成功,如果多个线程以一个CAS竞争,总会有一个胜出并前进。非阻塞算法堆死锁和优先级倒置有“免疫性”(但它们可能会出现饥饿和活锁,因为它们允许重进入)。
非阻塞算法通过使用低层次的并发原语,比如比较交换,取代了锁。原子变量类向用户提供了这些底层级原语,也能够当做“更佳的volatile变量”使用,同时提供了整数类和对象引用的原子化更新操作
‘伍’ 请分别给出三种不同的页面置换算法,并简要说明他们的优缺点
[fifo.rar]
-
操作系统中内存页面的先进先出的替换算法fifo
[先进先出页面算法程序.rar]
-
分别实现最佳置换算法(optimal)、先进先出(fifo)页面置换算法和最近最久未使用(LRU)置换算法,并给出各算法缺页次数和缺页率。
[0022.rar]
-
模拟分页式虚拟存储管理中硬件的地址转换和缺页中断,以及选择页面调度算法处理缺页中断
[Change.rar]
-
用java实现操作系统的页面置换
其中包括
最佳置换算法(Optimal)、先进先出算法(First-in,
First-out)
、最近最久不用的页面置换算法(LeastRecently
Used
Replacement)三种算法的实现
[M_Management.rar]
-
操作系统中内存管理页面置换算法的模拟程序,采用的是LRU置换算法
[detail_of_44b0x_TCPIP.rar]
-
TCPIP
程序包加载到44b0x
的ADS1.2工程文件的说明书。说名了加载过程的细节和如何处理演示程序和代码。演示代码已经上传,大家可以搜索
[.rar]
-
java操作系统页面置换算法:
(1)进先出的算法(fifo)
(2)最近最少使用的算法(LRU)
(3)最佳淘汰算法(OPT)
(4)最少访问页面算法(LFU)
(注:由本人改成改进型Clock算法)
(5)最近最不经常使用算法(NUR)
‘陆’ 用java语言实现LRU算法和FIFO算法。急急急!!!!!!!
您好,网络贴吧专家团很高兴能够回答您的问题。您的采纳是我们前进的动力。
public class LRU {
private int theArray[];
private int back; //定义队尾
private int currentSize; //队列中存放元素个数
private int maxSize=5; //队列中能存放元素的个数
public LRU(){
theArray=new int[maxSize];
back=0;
currentSize=0;
}
public void queue(int a[]){
for(int i=0;i<a.length;i++){
enQueue(a[i]);
}
}
public void enQueue(int x){ //入队
beUsed(x); //先判断是否已存在该页号,若存在,删除
if(currentSize<maxSize){
theArray[back]=x;
back++;
currentSize++;
}else if(currentSize==maxSize){ //满了
for(int i=0;i<maxSize-1;i++){
theArray[i]=theArray[i+1];
}
theArray[maxSize-1]=x;
}
for(int i=0;i<currentSize;i++){
System.out.print(theArray[i]);
}
System.out.println();
}
public void beUsed(int x){ //判断是否已存在该页号,若存在,删除已有的
for(int i=0;i<currentSize;i++){
if(theArray[i]==x){
for(int j=i;j<currentSize-1;j++){
theArray[j]=theArray[j+1];
}
currentSize--;
back--;
}
}
}
public static void main(String[] args) {
LRU lru=new LRU();
int a[]={4,7,0,7,1,0,1,2,1,2,6};
lru.queue(a);
}
}
‘柒’ java 用什么实现 FIFO队列
java使用数据结构来实现FIFO先进先出的队列,实例如下:
/*
*Tochangethistemplate,chooseTools|Templates
*andopenthetemplateintheeditor.
*/
packagelinkedlisttest;
importjava.util.ArrayList;
importjava.util.Deque;
importjava.util.LinkedList;
importjava.util.List;
/**
*
*@authorVicky.H
*@[email protected]
*/
publicclassFIFOTest{
/**
*@
*/
publicstaticvoidmain(String[]args){
FIFO<A>fifo=newFIFOImpl<A>(5);
for(inti=0;i<20;i++){
Aa=newA("A:"+i);
Ahead=fifo.addLastSafe(a);
System.out.println(i+" head:"+head+" size:"+fifo.size());
}
System.out.println("---------------");
System.out.println("弹出数据");
List<A>polls=fifo.setMaxSize(3);
for(Aa:polls){
System.out.println(" head:"+a);
}
System.out.println("剩余数据");
for(Aa:fifo){
System.out.println(" head:"+a);
}
System.out.println(fifo.size());
}
}
interfaceFIFO<T>extendsList<T>,Deque<T>,Cloneable,java.io.Serializable{
/**
*向最后添加一个新的,如果长度超过允许的最大值,则弹出一个*
*/
TaddLastSafe(TaddLast);
/**
*弹出head,如果Size=0返回null。而不同于pop抛出异常
*@return
*/
TpollSafe();
/**
*获得最大保存
*
*@return
*/
intgetMaxSize();
/**
*设置最大存储范围
*
*@return返回的是,因为改变了队列大小,导致弹出的head
*/
List<T>setMaxSize(intmaxSize);
}
classFIFOImpl<T>extendsLinkedList<T>implementsFIFO<T>{
privateintmaxSize=Integer.MAX_VALUE;
privatefinalObjectsynObj=newObject();
publicFIFOImpl(){
super();
}
publicFIFOImpl(intmaxSize){
super();
this.maxSize=maxSize;
}
@Override
publicTaddLastSafe(TaddLast){
synchronized(synObj){
Thead=null;
while(size()>=maxSize){
head=poll();
}
addLast(addLast);
returnhead;
}
}
@Override
publicTpollSafe(){
synchronized(synObj){
returnpoll();
}
}
@Override
publicList<T>setMaxSize(intmaxSize){
List<T>list=null;
if(maxSize<this.maxSize){
list=newArrayList<T>();
synchronized(synObj){
while(size()>maxSize){
list.add(poll());
}
}
}
this.maxSize=maxSize;
returnlist;
}
@Override
publicintgetMaxSize(){
returnthis.maxSize;
}
}
classA{
privateStringname;
publicA(){
}
publicA(Stringname){
this.name=name;
}
publicStringgetName(){
returnname;
}
publicvoidsetName(Stringname){
this.name=name;
}
@Override
publicStringtoString(){
return"A{"+"name="+name+'}';
}
}
‘捌’ 如何使用queue
Queue接口与List、Set同一级别,都是继承了Collection接口。LinkedList实现了Queue接 口。Queue接口窄化了对LinkedList的方法的访问权限(即在方法中的参数类型如果是Queue时,就完全只能访问Queue接口所定义的方法 了,而不能直接访问 LinkedList的非Queue的方法),以使得只有恰当的方法才可以使用。BlockingQueue 继承了Queue接口。
队列是一种数据结构.它有两个基本操作:在队列尾部加人一个元素,和从队列头部移除一个元素就是说,队列以一种先进先出的方式管理数据,如果你试图向一个 已经满了的阻塞队列中添加一个元素或者是从一个空的阻塞队列中移除一个元索,将导致线程阻塞.在多线程进行合作时,阻塞队列是很有用的工具。工作者线程可 以定期地把中间结果存到阻塞队列中而其他工作者线线程把中间结果取出并在将来修改它们。队列会自动平衡负载。如果第一个线程集运行得比第二个慢,则第二个 线程集在等待结果时就会阻塞。如果第一个线程集运行得快,那么它将等待第二个线程集赶上来。下表显示了jdk1.5中的阻塞队列的操作:
add 增加一个元索 如果队列已满,则抛出一个IIIegaISlabEepeplian异常
remove 移除并返回队列头部的元素 如果队列为空,则抛出一个NoSuchElementException异常
element 返回队列头部的元素 如果队列为空,则抛出一个NoSuchElementException异常
offer 添加一个元素并返回true 如果队列已满,则返回false
poll 移除并返问队列头部的元素 如果队列为空,则返回null
peek 返回队列头部的元素 如果队列为空,则返回null
put 添加一个元素 如果队列满,则阻塞
take 移除并返回队列头部的元素 如果队列为空,则阻塞
remove、element、offer 、poll、peek 其实是属于Queue接口。
阻塞队列的操作可以根据它们的响应方式分为以下三类:aad、removee和element操作在你试图为一个已满的队列增加元素或从空队列取得元素时 抛出异常。当然,在多线程程序中,队列在任何时间都可能变成满的或空的,所以你可能想使用offer、poll、peek方法。这些方法在无法完成任务时 只是给出一个出错示而不会抛出异常。
注意:poll和peek方法出错进返回null。因此,向队列中插入null值是不合法的。
还有带超时的offer和poll方法变种,例如,下面的调用:
boolean success = q.offer(x,100,TimeUnit.MILLISECONDS);
尝试在100毫秒内向队列尾部插入一个元素。如果成功,立即返回true;否则,当到达超时进,返回false。同样地,调用:
Object head = q.poll(100, TimeUnit.MILLISECONDS);
如果在100毫秒内成功地移除了队列头元素,则立即返回头元素;否则在到达超时时,返回null。
最后,我们有阻塞操作put和take。put方法在队列满时阻塞,take方法在队列空时阻塞。
java.ulil.concurrent包提供了阻塞队列的4个变种。默认情况下,LinkedBlockingQueue的容量是没有上限的(说的不准确,在不指定时容量为Integer.MAX_VALUE,不要然的话在put时怎么会受阻呢),但是也可以选择指定其最大容量,它是基于链表的队列,此队列按 FIFO(先进先出)排序元素。
ArrayBlockingQueue在构造时需要指定容量, 并可以选择是否需要公平性,如果公平参数被设置true,等待时间最长的线程会优先得到处理(其实就是通过将ReentrantLock设置为true来 达到这种公平性的:即等待时间最长的线程会先操作)。通常,公平性会使你在性能上付出代价,只有在的确非常需要的时候再使用它。它是基于数组的阻塞循环队 列,此队列按 FIFO(先进先出)原则对元素进行排序。
PriorityBlockingQueue是一个带优先级的 队列,而不是先进先出队列。元素按优先级顺序被移除,该队列也没有上限(看了一下源码,PriorityBlockingQueue是对 PriorityQueue的再次包装,是基于堆数据结构的,而PriorityQueue是没有容量限制的,与ArrayList一样,所以在优先阻塞 队列上put时是不会受阻的。虽然此队列逻辑上是无界的,但是由于资源被耗尽,所以试图执行添加操作可能会导致 OutOfMemoryError),但是如果队列为空,那么取元素的操作take就会阻塞,所以它的检索操作take是受阻的。另外,往入该队列中的元 素要具有比较能力。
最后,DelayQueue(基于PriorityQueue来实现的)是一个存放Delayed 元素的无界阻塞队列,只有在延迟期满时才能从中提取元素。该队列的头部是延迟期满后保存时间最长的 Delayed 元素。如果延迟都还没有期满,则队列没有头部,并且poll将返回null。当一个元素的 getDelay(TimeUnit.NANOSECONDS) 方法返回一个小于或等于零的值时,则出现期满,poll就以移除这个元素了。此队列不允许使用 null 元素。 下面是延迟接口:
Java代码
public
interface
Delayed
extends
Comparable<Delayed>
{
long
getDelay(TimeUnit
unit);
}
放入DelayQueue的元素还将要实现compareTo方法,DelayQueue使用这个来为元素排序。
下面的实例展示了如何使用阻塞队列来控制线程集。程序在一个目录及它的所有子目录下搜索所有文件,打印出包含指定关键字的文件列表。从下面实例可以看出,使用阻塞队列两个显着的好处就是:多线程操作共同的队列时不需要额外的同步,另外就是队列会自动平衡负载,即那边(生产与消费两边)处理快了就会被阻塞掉,从而减少两边的处理速度差距。下面是具体实现:
Java代码
public
class
BlockingQueueTest
{
public
static
void
main(String[]
args)
{
Scanner
in
=
new
Scanner(System.in);
System.out.print("Enter
base
directory
(e.g.
/usr/local/jdk5.0/src):
");
String
directory
=
in.nextLine();
System.out.print("Enter
keyword
(e.g.
volatile):
");
String
keyword
=
in.nextLine();
final
int
FILE_QUEUE_SIZE
=
10;//
阻塞队列大小
final
int
SEARCH_THREADS
=
100;//
关键字搜索线程个数
//
基于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
=
1;
i
<=
SEARCH_THREADS;
i++)
new
Thread(new
SearchTask(queue,
keyword)).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;
}
public
void
run()
{
try
{
enumerate(startingDirectory);
queue.put(DUMMY);//执行到这里说明指定的目录下文件已被遍历完
}
catch
(InterruptedException
e)
{
}
}
//
将指定目录下的所有文件以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;
}
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
(IOException
e)
{
e.printStackTrace();
}
catch
(InterruptedException
e)
{
}
}
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();
}
}