队列以一种先进先出的方式管理数据,如果你试图向一个已经满了的阻塞队列中添加一个元素,或是从一个空的阻塞队列中移除一个元素,将导致线程阻塞。在多线程进行合作时,阻塞队列是很有用的工具,工作者线程可以定期的把中间结果存到阻塞队列中,而其他工作者线程把中间结果取出并在将来修改它们。
AD:
队列以一种先进先出的方式管理数据。如果你试图向一个已经满了的阻塞队列中添加一个元素,或是从一个空的阻塞队列中移除一个元素,将导致线程阻塞。在多线程进行合作时,阻塞队列是很有用的工具。工作者线程可以定期的把中间结果存到阻塞队列中。而其他工作者线程把中间结果取出并在将来修改它们。队列会自动平衡负载。如果第一个线程集运行的比第二个慢,则第二个线程集在等待结果时就会阻塞。如果第一个线程集运行的快,那么它将等待第二个线程集赶上来。
下面的程序展示了如何使用阻塞队列来控制线程集。程序在一个目录及它的所有子目录下搜索所有文件,打印出包含指定关键字的文件列表。
java.util.concurrent包提供了阻塞队列的4个变种:LinkedBlockingQueue、ArrayBlockingQueue、PriorityBlockingQueue和DelayQueue。我们用的是ArrayBlockingQueue。ArrayBlockingQueue在构造时需要给定容量,并可以选择是否需要公平性。如果公平参数被设置了,等待时间最长的线程会优先得到处理。通常,公平性会使你在性能上付出代价,只有在的确非常需要的时候再使用它。
生产者线程枚举在所有子目录下的所有文件并把它们放到一个阻塞队列中。这个操作很快,如果队列没有设上限的话,很快它就包含了没有找到的文件。
我们同时还启动了大量的搜索线程。每个搜索线程从队列中取出一个文件,打开它,打印出包含关键字的所有行,然后取出下一个文件。我们使用了一个小技巧来在工作结束后终止线程。为了发出完成信号,枚举线程把一个虚拟对象放入队列。(这类似于在行李输送带上放一个写着“最后一个包”的虚拟包。)当搜索线程取到这个虚拟对象时,就将其放回并终止。
注意,这里不需要人任何显示的线程同步。在这个程序中,我们使用队列数据结构作为一种同步机制。
实例代码如下,复制即可
package com.pzoom.test.blockingQueue;
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;
/**
* Created with IntelliJ IDEA.
* User: Administrator
* Date: 13-2-22
* Time: 下午3:51
* 修改描述
*/
public class BlockingQueueTest2 {
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<File> queue = new ArrayBlockingQueue<File>(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();
}
}
/**
* 28 * This task enumerates all files in a directory and its subdirectories.
* 29
*/
class FileEnumerationTask implements Runnable {
/**
* 33 * Constructs a FileEnumerationTask.
* 34 * @param queue the blocking queue to which the enumerated files are added
* 35 * @param startingDirectory the directory in which to start the enumeration
* 36
*/
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) {
}
}
/**
* 56 * Recursively enumerates all files in a given directory and its subdirectories
* 57 * @param directory the directory in which to start
* 58
*/
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<File> queue;
private File startingDirectory;
}
/**
* 76 * This task searches files for a given keyword.
* 77
*/
class SearchTask implements Runnable {
/**
* 81 * Constructs a SearchTask.
* 82 * @param queue the queue from which to take files
* 83 * @param keyword the keyword to look for
* 84
*/
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) {
}
}
/**
* 117 * Searches a file for a given keyword and prints all matching lines.
* 118 * @param file the file to search
* 119
*/
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<File> queue;
private String keyword;
}
分享到:
相关推荐
通过以上分析,我们了解到基于Java阻塞队列的搜索实例利用了Java并发API的强大功能来实现多线程间的高效协作,从而完成复杂的文件搜索任务。在多线程编程实践中,理解阻塞队列的工作原理和正确使用它们是关键的一步...
本文将详细介绍一个基于Java实现的多线程文件上传系统,并结合队列管理技术来优化后台处理流程。该系统通过创建多个线程来并行处理客户端的文件上传请求,同时利用队列结构来协调任务的调度与执行。 #### 关键技术...
总结来说,Java阻塞队列是一种强大的并发工具,它通过自动阻塞和唤醒线程来实现线程间的同步,简化了多线程编程的复杂性。在Java `java.util.concurrent`包中提供了多种优化的阻塞队列实现,适用于不同的并发需求。...
Java阻塞队列实现原理及实例解析 Java阻塞队列是一种特殊的队列,它能够在队列为空或满时阻塞线程,使得线程之间能够更好地协作和通信。阻塞队列的实现原理是基于锁机制和条件变量机制的,通过wait和notify方法来...
Java中的阻塞队列BlockingQueue是一种并发编程中常用的工具,它实现了线程间的同步和通信。阻塞队列的核心特性在于当队列为空时,尝试获取元素的线程会被阻塞,直到其他线程添加元素;当队列满时,尝试添加元素的...
队列工厂则是实现多线程间通信和任务调度的一种设计模式,它提供了一种抽象和统一的方式来创建和管理队列实例。 ### 1. Java 多线程 多线程是指在单个程序中同时执行多个线程(任务)的能力。Java通过`Thread`类和...
在上述实例中,阻塞队列被用来控制线程集,以便在目录及其子目录中搜索包含特定关键字的文件。这个程序涉及到几个关键的Java并发概念和技术,包括线程、阻塞队列以及并发容器类。 首先,阻塞队列是一种特殊类型的...
本实例源码提供了基于Java的MDB实现,帮助开发者深入理解其工作原理。 首先,我们需要了解EJB的基本概念。Enterprise JavaBeans是Java平台企业版(Java EE)的一部分,提供了一种组件模型,用于构建可部署在服务器...
5. **I/O流**:在Java中,`InputStream`和`OutputStream`是用于读写文件的基础类,多线程传输时,每个线程可以拥有自己的输入/输出流实例,分别处理文件的一部分。 6. **异常处理**:多线程环境下,需要确保每个...
本资源“Java GUI实例下载”提供了一系列关于Java GUI编程的实例,涵盖了事件处理、布局管理以及各种控件的使用,旨在帮助初学者和开发者深入理解和实践Java GUI编程。 1. **事件处理**:在Java GUI中,事件处理是...
首先,`LinkedBlockingQueue`是Java并发库`java.util.concurrent`中的一个线程安全的数据结构,它是一种阻塞队列。阻塞队列在满时会阻塞生产者,空时会阻塞消费者,这样可以很好地协调生产者和消费者的执行节奏。`...
该压缩包文件“基于Java的实例源码-HAHA CHAT Java仿QQ聊天程序源代码.zip”提供了一个名为“HAHA CHAT”的Java聊天程序的完整源代码,它旨在模仿QQ聊天软件的功能和用户体验。这个项目对于学习Java编程、网络通信、...
Java消息服务(JMS,Java Message Service)是Java平台中用于企业级应用集成的一个标准API,它提供了一种可靠和高效的方式来进行异步通信。在JMS中,消息被发送到一个消息代理(message broker),然后由消费者从该...
Spring框架是Java开发领域广泛使用的轻量级开源框架,它提供了对消息队列的支持,使得开发者可以方便地集成消息队列到Spring应用中。在这个基于Spring的消息队列系统中,前端Web应用通过并发发送Ajax请求来获取数据...
本文将深入讲解Java内置队列类Queue的使用方法,并通过实例来展示其功能。 首先,`java.util.Queue`是Java集合框架的一部分,它是所有队列类型的父接口。Queue接口提供了多种方法用于操作队列,包括添加元素、移除...
java队列之queue用法实例分析 java队列之queue用法实例分析主要介绍了java队列之queue用法实例分析,Queue 队列就是一个先入先出(FIFO)的数据结构,Queue接口继承Collection接口。Queue接口与List、Set同一级别,...
在"java高级编程100实例"这个资源中,尽管实例数量可能未达到100,但它们仍然能为开发者提供宝贵的实践经验,帮助他们深入理解和掌握Java的高级特性。 1. **多线程编程**:Java提供了强大的并发支持,如Thread类和...
在本Java实例中,我们探讨的是一个经典的桌面游戏——连连看的实现,它是一个基于Java编程语言的游戏项目。连连看游戏通常包含两个主要部分:游戏逻辑和用户界面。以下将详细解析这两个方面以及相关的Java技术。 **...
Java中的阻塞队列(BlockingQueue)是一种线程安全的数据结构,它在多线程环境下的生产者消费者问题中扮演着关键角色。阻塞队列的主要特点是当队列满时,生产者线程会等待,直到队列有空位;同样,当队列为空时,...