java中队列Queue的使用
1、在java5中新增加了java.util.Queue接口,用以支持队列的常见操作。Queue接口与List、Set同一级别,都是继承了Collection接口。
Queue使用时要尽量避免Collection的add()和remove()方法,而是要使用offer()来加入元素,使用poll()来获取并移出元素。它们的优
点是通过返回值可以判断成功与否,add()和remove()方法在失败的时候会抛出异常。 如果要使用前端而不移出该元素,使用
element()或者peek()方法。
2、值得注意的是LinkedList类实现了Queue接口,因此我们可以把LinkedList当成Queue来用。
3、LinkedList实现了Queue接口。Queue接口窄化了对LinkedList的方法的访问权限(即在方法中的参数类型如果是Queue时,就完全只能访问Queue接口所定义的方法 了,而不能直接访问 LinkedList的非Queue的方法),以使得只有恰当的方法才可以使用。BlockingQueue 继承了Queue接口。
4、队列是一种数据结构.它有两个基本操作:在队列尾部加人一个元素,和从队列头部移除一个元素就是说,队列以一种先进先出的方式管理数据,如果你试图向一个 已经满了的阻塞队列中添加一个元素或者是从一个空的阻塞队列中移除一个元索,将导致线程阻塞.在多线程进行合作时,阻塞队列是很有用的工具。工作者线程可 以定期地把中间结果存到阻塞队列中而其他工作者线线程把中间结果取出并在将来修改它们。队列会自动平衡负载。如果第一个线程集运行得比第二个慢,则第二个 线程集在等待结果时就会阻塞。如果第一个线程集运行得快,那么它将等待第二个线程集赶上来。下表显示了jdk1.5中的阻塞队列的操作:
add 增加一个元索 如果队列已满,则抛出一个IIIegaISlabEepeplian异常
remove 移除并返回队列头部的元素 如果队列为空,则抛出一个NoSuchElementException异常
element 返回队列头部的元素 如果队列为空,则抛出一个NoSuchElementException异常
offer 添加一个元素并返回true 如果队列已满,则返回false
poll 移除并返问队列头部的元素 如果队列为空,则返回null
peek 返回队列头部的元素 如果队列为空,则返回null
put 添加一个元素 如果队列满,则阻塞
take 移除并返回队列头部的元素 如果队列为空,则阻塞
remove、element、offer 、poll、peek 其实是属于Queue接口。
5、阻塞队列的操作可以根据它们的响应方式分为以下三类:aad、removee和element操作在你试图为一个已满的队列增加元素或从空队列取得元素时 抛出异常。当然,在多线程程序中,队列在任何时间都可能变成满的或空的,所以你可能想使用offer、poll、peek方法。这些方法在无法完成任务时 只是给出一个出错示而不会抛出异常。
6、注意:poll和peek方法出错进返回null。因此,向队列中插入null值是不合法的。
7、
还有带超时的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 元素。 下面是延迟接口:
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();
}
}
java中队列Queue的使用的更多相关文章
- Java中的queue和deque对比详解
队列(queue)简述 队列(queue)是一种常用的数据结构,可以将队列看做是一种特殊的线性表,该结构遵循的先进先出原则.Java中,LinkedList实现了Queue接口,因为LinkedLis ...
- java中并发Queue种类与各自API特点以及使用场景!
一 先说下队列 队列是一种数据结构.它有两个基本操作:在队列尾部加入一个元素,和从队列头部移除一个元素(注意不要弄混队列的头部和尾部) 就是说,队列以一种先进先出的方式管理数据,如果你试图向一个 已经 ...
- Java 中队列同步器 AQS(AbstractQueuedSynchronizer)实现原理
前言 在 Java 中通过锁来控制多个线程对共享资源的访问,使用 Java 编程语言开发的朋友都知道,可以通过 synchronized 关键字来实现锁的功能,它可以隐式的获取锁,也就是说我们使用该关 ...
- STL中队列queue的用法
头文件:#include <queue> 建立一个队列queue < 类型 > q 加入一个新的元素q.push(a) 询问队首元素q.front() 弹出队首元素q.pop( ...
- Java 中队列的使用
刚才看见群里的一个朋友在问队列的使用,确实在现实的写代码中非常少使用队列的,反正我是从来没使用过.仅仅是学数据结构的时候学过. 以下是我写的一个小样例,希望有不足之处请提出改正.O(∩_∩)O~ 看代 ...
- c++中队列queue和栈stack的基本操作
1.queue 模板类的定义在<queue>头文件中. 定义queue 对象的示例代码如下:queue<int> q1;queue<double> q2; queu ...
- Java中队列
定义 队的操作是在两端进行,一端只能进行插入操作(入队),称为队尾,一端只能进行删除操作(出队),称为队尾. 队列的运算规则是FIFO(first in first out). 队列的入队.出队操作分 ...
- JAVA中常见的阻塞队列详解
在之前的线程池的介绍中我们看到了很多阻塞队列,这篇文章我们主要来说说阻塞队列的事. 阻塞队列也就是 BlockingQueue ,这个类是一个接 口,同时继承了 Queue 接口,这两个接口都是在JD ...
- Java 中的队列 Queue
一.队列的定义 我们都知道队列(Queue)是一种先进先出(FIFO)的数据结构,Java中定义了java.util.Queue接口用来表示队列.Java中的Queue与List.Set属于同一个级别 ...
随机推荐
- iOS扩展——Objective-C开发编程规范
最近准备开始系统学习一个完整项目的开发流程和思路,在此之前,我们需要对iOS的开发变成规范进行更系统和详尽的学习,随意对编程规范进行了整理和学习.本文内容主要转载自:Objective-C-Codin ...
- typedef和define具体的详细区别
1) #define是预处理指令,在编译预处理时进行简单的替换,不作正确性检查,不关含义是否正确照样带入,只有在编译已被展开的源程序时才会发现可能的错误并报错.例如: #define PI 3.141 ...
- oracle创建触发器及作用举例
--创建触发器及作用举例 create or replace trigger tri before delete on emp --在删除emp表数据之前需要做的事根据自己的业务去写,before是在 ...
- 注意SSIS中的DT_NUMERIC类型转换为字符类型(比如DT_WSTR)时,会截断小数点前的0
我们知道SSIS中有许多数据类型,如下图所示: 但是DT_NUMERIC这个类型有个陷进要注意,我们来做个实验,随便定义一个String类型的SSIS包变量,然后打开该变量表达式窗口: 在变量表达式窗 ...
- 零基础教你写python爬虫
大家都知道python经常被用来做爬虫,用来在互联网上抓取我们需要的信息. 使用Python做爬虫,需要用到一些包: requests urllib BeautifulSoup 等等,关于python ...
- Oracle创建、管理撤销表空间
撤销管理模式: 用户通过设定撤销管理模式(undo mode)就可以灵活地选择使用手动撤销管理(manual undo management)或自动撤销管理(automatic undo manage ...
- Oracle实战笔记(第六天)之PL/SQL基础
一.PL/SQL介绍 1.概念 PL/SQL也是一种程序语言,叫做过程化SQL语言(Procedural Language/SQL).PL/SQL是Oracle数据库对SQL语句的扩展.在普通SQL语 ...
- 异步式I/O与实践式编程
阻塞 线程在执行中如果遇到磁盘读写或网络通信(统称为I/O操作)通常要消耗很长时间 这时操作系统会剥夺这个线程的CPU控制权,使其暂停执行,同时将资源让给其他工作线程 异步I/O 非阻塞IO 针对所有 ...
- Azure Powershell获取指定订阅下的虚拟机信息(ASM)
为方便Azure用户导出已创建虚拟机的相关信息,特编写如下脚本: 详情脚本: # 登陆Azure Account Add-AzureAccount -Environment AzureChinaClo ...
- CentOS6.x机器安装Azure CLI2.0【2】
安装Azure CLI 2.0的前提是:机器中必须有 Python 2.7.x 或 Python 3.x.如果机器中没有其中任何一个Python版本,请及时安装 1.准备一台CentOS 6.9的机器 ...