`

队列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代码
  1. public interface Delayed extends Comparable<Delayed> {  
  2.      long getDelay(TimeUnit unit);  
  3. }  

放入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();  
    }  
}  
 
分享到:
评论

相关推荐

    消息队列 Queue与Topic区别.docx

    ### 消息队列Queue与Topic的区别 #### 一、概念概述 消息队列(Message Queue)是一种应用程序间通信机制,允许程序之间通过发送和接收消息进行通信,而不必直接建立连接。它提供了异步处理机制,使得消息的发送者...

    设一循环队列Queue,只有头指针front,不设尾指针,另设一个内含元素个数的计数器,试写出相应的进队、出队算法。

    设一循环队列Queue,只有头指针front,不设尾指针,另设一个内含元素个数的计数器,试写出相应的进队、出队算法。

    C#队列Queue多线程用法实例

    在C#编程中,队列(Queue)...总结来说,这个实例展示了如何在C#中使用队列Queue进行多线程编程,包括创建队列、入队、出队以及创建和启动线程。理解这些基本概念和操作对于开发涉及多线程和队列的C#应用程序至关重要。

    c++消息队列queue.rar

    "c++消息队列queue.rar"可能包含了一个关于如何在C++中使用消息队列,特别是标准库中的`std::queue`容器的相关示例或教程。`std::queue`是C++标准模板库(STL)的一部分,它提供了一种FIFO(先进先出)的数据结构,...

    数据结构 严蔚敏 队列 queue

    数据结构 严蔚敏 队列 queue

    线程安全队列Queue

    ### 线程安全队列Queue #### 一、背景介绍 在开发多线程应用时,线程安全成为至关重要的考量因素之一。特别是在需要处理并发任务时,如何确保线程之间的安全通信变得尤为重要。本篇文章将围绕一个具体的场景——...

    基于python的数据结构代码实现-队列Queue

    队列Queue是一种常用的数据结构,遵循“先进先出”(First In First Out, FIFO)原则,即最早添加到队列中的元素最先被移除。本教程将深入探讨如何在Python中实现队列Queue的数据结构。 首先,Python标准库提供了`...

    Unity3d 队列 方法 Queue

    ### Unity3D中的队列(Queue)方法解析与应用实例 #### 一、概述 在Unity3D开发中,队列是一种非常实用的数据结构,它遵循先进先出(First In First Out, FIFO)的原则,即最先加入队列的元素会最先被移除。队列在...

    基于C语言的数据结构-队列queue

    在本主题“基于C语言的数据结构-队列queue”中,我们将深入探讨如何在C语言中实现队列的数据结构。 队列的基本操作包括: 1. **入队**(Enqueue):将元素添加到队列的末尾。 2. **出队**(Dequeue):移除并返回...

    python 队列Queue的使用 python2例程展示了队列Queue的使用过程,供学习参考使用

    Python中的`queue`模块提供了多种类型的队列,包括`Queue`(默认限制大小)、`LifoQueue`(后进先出,类似堆栈)和`PriorityQueue`(优先级队列)。这些队列都实现了线程安全的`put()`和`get()`方法,用于添加和获取...

    队列queue的实现

    `std::queue`是一个基本的FIFO队列,而`std::priority_queue`则是一个最小堆实现的优先级队列。我们将主要关注`std::queue`的实现。 ### `std::queue`基础 `std::queue`是一个容器适配器,它使用其他容器(通常是`...

    python队列Queue的详解

    Queue是python标准库中的线程安全的队列(FIFO)实现,提供了一个适用于多线程编程的先进先出的数据结构,即队列,用来在生产者和消费者线程之间的信息传递 基本FIFO队列 class Queue.Queue(maxsize=0) FIFO即First ...

    第九周-第14章节-Python3.5-队列Queue.avi

    第九周-第14章节-Python3.5-队列Queue.avi

    C#队列Queue用法实例分析

    本文实例分析了C#队列Queue用法。分享给大家供大家参考。具体分析如下: 队列(Queue)在程序设计中扮演着重要的角色,因为它可以模拟队列的数据操作。例如,排队买票就是一个队列操作,后来的人排在后面,先来的人...

    C语言实现的队列Queue

    队列(Queue)是一种线性数据结构,遵循“先进先出”(First In First Out, FIFO)的原则,就像现实生活中的排队一样,最早进入队列的元素最先离开。在这个主题中,我们将深入探讨如何使用C语言实现一个队列。 ...

    堆栈Stack, 队列Queue【数据结构和算法入门5】

    堆栈Stack,_队列Queue【数据结构和算法入门5】

    C++类 队列 queue

    用C++类实现队列功能。 包含添加、删除、初始化。

    ActiveMQ的队列queue模式(事务、应答、转发模式、阻塞消息)

    本文将深入探讨ActiveMQ中的队列(Queue)模式,包括事务、应答、转发以及MessageConsumer的receive阻塞消息处理方式。 ### 1. ActiveMQ队列(Queue)模式 在ActiveMQ中,队列是一种点对点的消息传递模型,每个...

    java 自定义Queue队列

    在Java编程语言中,`Queue`接口是集合框架的一部分,它代表了先进先出(FIFO)的数据结构,也就是我们通常所说的队列。队列是一种非常基础且实用的数据结构,广泛应用于多线程同步、任务调度、缓存管理等多个场景。...

Global site tag (gtag.js) - Google Analytics