`
tomcat_oracle
  • 浏览: 311726 次
社区版块
存档分类
最新评论

基于Java阻塞队列的搜索实例

阅读更多

队列以一种先进先出的方式管理数据。如果你试图向一个已经满了的阻塞队列中添加一个元素,或是从一个空的阻塞队列中移除一个元素,将导致线程阻塞。在多线程进行合作时,阻塞队列是很有用的工具。工作者线程可以定期的把中间结果存到阻塞队列中。而其他工作者线程把中间结果取出并在将来修改它们。队列会自动平衡负载。如果第一个线程集运行的比第二个慢,则第二个线程集在等待结果时就会阻塞。如果第一个线程集运行的快,那么它将等待第二个线程集赶上来。

  下面的程序展示了如何使用阻塞队列来控制线程集。程序在一个目录及它的所有子目录下搜索所有文件,打印出包含指定关键字的文件列表。

  java.util.concurrent包提供了阻塞队列的4个变种:LinkedBlockingQueue、ArrayBlockingQueue、PriorityBlockingQueue和DelayQueue。我们用的是ArrayBlockingQueue。ArrayBlockingQueue在构造时需要给定容量,并可以选择是否需要公平性。如果公平参数被设置了,等待时间最长的线程会优先得到处理。通常,公平性会使你在性能上付出代价,只有在的确非常需要的时候再使用它。

  生产者线程枚举在所有子目录下的所有文件并把它们放到一个阻塞队列中。这个操作很快,如果队列没有设上限的话,很快它就包含了没有找到的文件。

  我们同时还启动了大量的搜索线程。每个搜索线程从队列中取出一个文件,打开它,打印出包含关键字的所有行,然后取出下一个文件。我们使用了一个小技巧来在工作结束后终止线程。为了发出完成信号,枚举线程把一个虚拟对象放入队列。(这类似于在行李输送带上放一个写着“最后一个包”的虚拟包。)当搜索线程取到这个虚拟对象时,就将其放回并终止。

  注意,这里不需要人任何显示的线程同步。在这个程序中,我们使用队列数据结构作为一种同步机制。

 

import java.io.*; 
import java.util.*; 
import java.util.concurrent.*; 
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/jdk1.6.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; 
   BlockingQueue 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, keyword)).start(); } } 
/** 
* This task enumerates all files in a directory and its subdirectories. 
*/ 
class FileEnumerationTask implements Runnable { 
/** 
* Constructs a FileEnumerationTask. 
* @param queue the blocking queue to which the enumerated files are added 
* @param startingDirectory the directory in which to start the enumeration 
*/ 
public FileEnumerationTask(BlockingQueue queue, File startingDirectory) { 
    this.queue = queue; this.startingDirectory = startingDirectory; 
} 
public void run() { 
    try { 
        enumerate(startingDirectory); 
        queue.put(DUMMY); 
     } catch (
        InterruptedException e) { } 
} 

/** 
* Recursively enumerates all files in a given directory and its subdirectories 
* @param directory the directory in which to start 
*/ 
public void enumerate(File directory) throws InterruptedException { 
  File[] files = directory.listFiles(); 
   for (File file : files) { 
   if (file.isDirectory()) 
       enumerate(file); 
   else queue.put(file); 
  } 
} 
public static File DUMMY = new File("");
private BlockingQueue queue; private File startingDirectory; 
} 
/** 
* This task searches files for a given keyword. 
*/ 
class SearchTask implements Runnable { 
/** 
* Constructs a SearchTask. 
* @param queue the queue from which to take files 
* @param keyword the keyword to look for */ 
public SearchTask(BlockingQueue 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) { }
 } 
/** 
* Searches a file for a given keyword and prints all matching lines. 
* @param file the file to search 
*/ 
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().trim(); 
    if (line.contains(keyword)) System.out.printf("%s:%d %s%n", file.getPath(), lineNumber,line); 
   } 
  in.close(); 
} 
private BlockingQueue queue; 
private String keyword; 
}

 

 

8
2
分享到:
评论
1 楼 huangyunbin 2013-10-17  
感觉你这个代码有问题:
boolean done = false;   
        while (!done) {   
          File file = queue.take();   
          if (file == FileEnumerationTask.DUMMY) {   
            queue.put(file); done = true;  


你    queue.put(DUMMY);   你只put进去一个DUMMY。那么其实只有一个线程会停下来。
你一个线程done 改为true,不会影响到其他线程的。
其他线程一直会queue.take();  就是会一直阻塞。

相关推荐

    java学习(基于Java阻塞队列的搜索实例).pdf

    java学习(基于Java阻塞队列的搜索实例).pdf

    java阻塞队列实现原理及实例解析.docx

    java阻塞队列实现原理及实例解析.docx

    java阻塞队列实现原理及实例解析

    主要介绍了java阻塞队列实现原理及实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

    java 中 阻塞队列BlockingQueue详解及实例

    主要介绍了java 中 阻塞队列BlockingQueue详解及实例的相关资料,需要的朋友可以参考下

    Java中使用阻塞队列控制线程集实例

    主要介绍了Java控制阻塞队列线程集实例,本文用一个程序展示了如何使用阻塞队列来控制线程集,程序功能是在一个目录及它的所有子目录下搜索所有文件,打印出包含指定关键字的文件列表,需要的朋友可以参考下

    Java使用阻塞队列控制线程通信的方法实例详解

    主要介绍了Java使用阻塞队列控制线程通信的方法,结合实例形式详细分析了java使用阻塞队列控制线程通信的相关原理、方法及操作注意事项,需要的朋友可以参考下

    Java 阻塞队列详解及简单使用

    主要介绍了Java 阻塞队列详解及简单使用的相关资料,需要的朋友可以参考下

    JAVA上百实例源码以及开源项目源代码

    摘要:Java源码,初学实例,基于EJB的真实世界模型  基于EJB的真实世界模型,附源代码,部分功能需JSP配合完成。 J2ME优化压缩PNG文件 4个目标文件 内容索引:JAVA源码,综合应用,J2me游戏,PNG,图形处理  这是个J2ME...

    队列写入mysql实例

    LinkedBlockingQueue以及redis队列写入mysql实例

    JAVA上百实例源码以及开源项目

    摘要:Java源码,初学实例,基于EJB的真实世界模型  基于EJB的真实世界模型,附源代码,部分功能需JSP配合完成。 J2ME优化压缩PNG文件 4个目标文件 内容索引:JAVA源码,综合应用,J2me游戏,PNG,图形处理  这是个J2ME...

    Java开发实战1200例(第1卷).(清华出版.李钟尉.陈丹丹).part3

    实例141 使用阻塞队列实现线程同步 183 实例142 新建有返回值的线程 184 实例143 使用线程池优化多线程编程 186 实例144 Object类中线程相关的方法 187 实例145 哲学家就餐问题 189 实例146 使用信号量实现线程同步 ...

    java开源包6

    AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器 j2wap j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是...

    java开源包4

    AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器 j2wap j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是...

    java开源包9

    AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器 j2wap j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是...

    java开源包11

    AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器 j2wap j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是...

    java开源包101

    AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器 j2wap j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是...

Global site tag (gtag.js) - Google Analytics