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 元素。 下面是延迟接口:

Java代码

public interface Delayed extends Comparable<Delayed>{
  long getDelay(TimeUnit unit);
}

放入DelayQueue的元素还将要实现compareTo方法,DelayQueue使用这个来为元素排序。

 1 Java代码
 2 public class BlockingQueueTest {
 3     public static void main(String[] args) {
 4         Scanner in = new Scanner(System.in);
 5         System.out.print("Enter base directory (e.g. /usr/local/jdk5.0/src): ");
 6         String directory = in.nextLine();
 7         System.out.print("Enter keyword (e.g. volatile): ");
 8         String keyword = in.nextLine();
 9
10         final int FILE_QUEUE_SIZE = 10;// 阻塞队列大小
11         final int SEARCH_THREADS = 100;// 关键字搜索线程个数
12
13         // 基于ArrayBlockingQueue的阻塞队列
14         BlockingQueue<File> queue = new ArrayBlockingQueue<File>(
15                 FILE_QUEUE_SIZE);
16
17         //只启动一个线程来搜索目录
18         FileEnumerationTask enumerator = new FileEnumerationTask(queue,
19                 new File(directory));
20         new Thread(enumerator).start();
21
22         //启动100个线程用来在文件中搜索指定的关键字
23         for (int i = 1; i <= SEARCH_THREADS; i++)
24             new Thread(new SearchTask(queue, keyword)).start();
25     }
26 }
27 class FileEnumerationTask implements Runnable {
28     //哑元文件对象,放在阻塞队列最后,用来标示文件已被遍历完
29     public static File DUMMY = new File("");
30
31     private BlockingQueue<File> queue;
32     private File startingDirectory;
33
34     public FileEnumerationTask(BlockingQueue<File> queue, File startingDirectory) {
35         this.queue = queue;
36         this.startingDirectory = startingDirectory;
37     }
38
39     public void run() {
40         try {
41             enumerate(startingDirectory);
42             queue.put(DUMMY);//执行到这里说明指定的目录下文件已被遍历完
43         } catch (InterruptedException e) {
44         }
45     }
46
47     // 将指定目录下的所有文件以File对象的形式放入阻塞队列中
48     public void enumerate(File directory) throws InterruptedException {
49         File[] files = directory.listFiles();
50         for (File file : files) {
51             if (file.isDirectory())
52                 enumerate(file);
53             else
54                 //将元素放入队尾,如果队列满,则阻塞
55                 queue.put(file);
56         }
57     }
58 }
59 class SearchTask implements Runnable {
60     private BlockingQueue<File> queue;
61     private String keyword;
62
63     public SearchTask(BlockingQueue<File> queue, String keyword) {
64         this.queue = queue;
65         this.keyword = keyword;
66     }
67
68     public void run() {
69         try {
70             boolean done = false;
71             while (!done) {
72                 //取出队首元素,如果队列为空,则阻塞
73                 File file = queue.take();
74                 if (file == FileEnumerationTask.DUMMY) {
75                     //取出来后重新放入,好让其他线程读到它时也很快的结束
76                     queue.put(file);
77                     done = true;
78                 } else
79                     search(file);
80             }
81         } catch (IOException e) {
82             e.printStackTrace();
83         } catch (InterruptedException e) {
84         }
85     }
86     public void search(File file) throws IOException {
87         Scanner in = new Scanner(new FileInputStream(file));
88         int lineNumber = 0;
89         while (in.hasNextLine()) {
90             lineNumber++;
91             String line = in.nextLine();
92             if (line.contains(keyword))
93                 System.out.printf("%s:%d:%s%n", file.getPath(), lineNumber,
94                         line);
95         }
96         in.close();
97     }
98 }  

时间: 2024-10-12 15:06:01

java中队列Queue的使用的相关文章

Java中的queue和deque

队列(queue)是一种常用的数据结构,可以将队列看做是一种特殊的线性表,该结构遵循的先进先出原则.Java中,LinkedList实现了Queue接口,因为LinkedList进行插入.删除操作效率较高 相关常用方法: boolean offer(E e):将元素追加到队列末尾,若添加成功则返回true. E poll():从队首删除并返回该元素. E peek():返回队首元素,但是不删除 示例代码: public class QueueDemo { public static void m

STL中队列queue的用法

头文件:#include <queue> 建立一个队列queue < 类型 > q 加入一个新的元素q.push(a) 询问队首元素q.front() 弹出队首元素q.pop() 队里面有多少个元素q.size() 原文地址:https://www.cnblogs.com/yujh01/p/queue.html

Java 中队列的使用

刚才看见群里的一个朋友在问队列的使用,确实在现实的写代码中非常少使用队列的,反正我是从来没使用过.仅仅是学数据结构的时候学过. 以下是我写的一个小样例,希望有不足之处请提出改正.O(∩_∩)O~ 看代码: import java.util.LinkedList; import java.util.Queue; public class TestQueue { /** * @param args * @author JavaAlpha * Info 測试队列 */ public static vo

java中队列实现

队列的定义: 队列(Queue)是只允许在一端进行插入,而在另一端进行删除的运算受限的线性表. (1)允许删除的一端称为队头(Front). (2)允许插入的一端称为队尾(Rear).(3)当队列中没有元素时称为空队列.(4)队列亦称作先进先出(First In First Out)的线性表,简称为FIFO表.   队列的修改是依先进先出的原则进行的.新来的成员总是加入队尾,每次离开的成员总是队列头上的(不允许中途离队). 队列的存储结构及实现 队列的顺序存储结构 (1) 顺序队列的定义: 队列

Java中队列

定义 队的操作是在两端进行,一端只能进行插入操作(入队),称为队尾,一端只能进行删除操作(出队),称为队尾. 队列的运算规则是FIFO(first in first out). 队列的入队.出队操作分别具有入队和出队的指针,通常以f(front) 表示队首指针,r(rear)表示队尾指针. 队列的存储具有顺序存储和链式存储两种方式. 基本运算: 初始化: 判断空: 判断满: 入队: 出队: 取出队首元素. package com.wuwii.test; /** * 队列 * @author Zh

Java Collection之Queue具体解释及用途

Queue是一种常见的数据结构,其主要特征在于FIFO(先进先出),Java中的Queue是这样定义的: public interface Queue<E> extends Collection<E> { E element(); boolean offer(E o); E peek(); E poll(); E remove(); } 尽管Queue都具有FIFO的特点.但详细输出哪一个元素,Queue的各种实现是不同的,尤其是在排序的情况下,新输入的元素并不是放入队列尾部,而是

Java Collection之Queue详解及用途

Queue是一种常见的数据结构,其主要特征在于FIFO(先进先出),Java中的Queue是这样定义的: public interface Queue<E> extends Collection<E> { E element(); boolean offer(E o); E peek(); E poll(); E remove(); } 虽然Queue都具有FIFO的特点,但具体输出哪一个元素,Queue的各种实现是不同的,尤其是在排序的情况下,新输入的元素并非放入队列尾部,而是放

java中使用FIFO队列:java.util.Queue实现多台服务器发邮件的代码

代码下载地址:http://www.zuidaima.com/share/1838230785625088.htm 原文:java中使用FIFO队列:java.util.Queue实现多台服务器发邮件的代码 最近由于zuidaima.com注册用户的增多,qq企业邮箱发送邮件会被封禁账号导致注册后面的用户收不到周总结,所以紧急开发了一套多账号,多服务器发送邮件的程序. 大概的设计思路如下: 1.服务器可以无限扩展,但由于qq企业邮箱是限定域名,所以要想多服务器还得有多域名,多账号也不行. 2.最

Java多线程总结之线程安全队列Queue

在Java多线程应用中,队列的使用率很高,多数生产消费模型的首选数据结构就是队列.Java提供的线程安全的Queue可以分为阻塞队列和非阻塞队列,其中阻塞队列的典型例子是BlockingQueue,非阻塞队列的典型例子是ConcurrentLinkedQueue,在实际应用中要根据实际需要选用阻塞队列或者非阻塞队列. 注:什么叫线程安全?这个首先要明确.线程安全的类 ,指的是类内共享的全局变量的访问必须保证是不受多线程形式影响的.如果由于多线程的访问(比如修改.遍历.查看)而使这些变量结构被破坏