zoukankan      html  css  js  c++  java
  • Java Queue 专题

    关于java中的Queue,经常用到,做个总结 

        Queue是一种很常见的数据结构类型,在java里面Queue是一个接口,它只是定义了一个基本的Queue应该有哪些功能规约。

    (Java中的集合包括三大类,它们是Set、List和Map,它们都处于java.util包中,Set、List和Map都是接口,它们有各自的实现类。如果想了解更多的关于java集合方面的知识,
    请参考:Java 常用数据结构对象的实现原理 集合类 List Set Map 哪些线程安全 (美团面试题目)

    实际上有多个Queue的实现,有的是采用线性表实现,有的基于链表实现。还有的适用于多线程的环境。java中具有Queue功能的类主要有如下几个:AbstractQueue, ArrayBlockingQueue, ConcurrentLinkedQueue, LinkedBlockingQueue, DelayQueue, LinkedList, PriorityBlockingQueue, PriorityQueue和ArrayDqueue。在本文中,我们主要讨论常用的两种实现:LinkedList和ArrayDeque。 如果想了解多线程执行的AQS  (AbstractQueuedSynchronizer)算法 参考:解决多线程安全问题-无非两个方法synchronized和lock 具体原理以及如何 获取锁AQS算法 (百度-美团)

    Queue

         Queue本身是一种先入先出的模型(FIFO),和我们日常生活中的排队模型很类似。根据不同的实现,他们主要有数组和链表两种实现形式。如下图:

        因为在队列里和我们日常的模型很近似,每次如果要出队的话,都是从队头移除。而如果每次要加入新的元素,则要在队尾加。所以我们要在队列里保存队头和队尾。

        在jdk里几个常用队列实现之间的类关系图如下:

        我们可以看到,Deque也是一个接口,它继承了Queue的接口规范。我们要讨论的LinkedList和ArrayDeque都是实现Deque接口,所以,可以说他们俩都是双向队列。具体的实现我们会在后面讨论。

    Queue 的具体操作为:

    public interface Queue<E> extends Collection<E> {  
      
        boolean add(E e); // 添加元素到队列中,相当于进入队尾排队。  
      
        boolean offer(E e);  //添加元素到队列中,相当于进入队尾排队.  
      
        E remove(); //移除队头元素  
      
        E poll();  //移除队头元素  
      
        E element(); //获取但不移除队列头的元素  
      
        E peek();  //获取但不移除队列头的元素  
    }  

    Queue作为一个接口,它声明的几个基本操作无非就是入队和出队的操作,具体定义如下:

    import java.util.LinkedList;
    import java.util.Queue;
     
    public class Main {
        public static void main(String[] args) {
            //add()和remove()方法在失败的时候会抛出异常(不推荐)
            Queue<String> queue = new LinkedList<String>();
            //添加元素
            queue.offer("a");
            queue.offer("b");
            queue.offer("c");
            queue.offer("d");
            queue.offer("e");
            for(String q : queue){
                System.out.println(q);
            }
            System.out.println("===");
            System.out.println("poll="+queue.poll()); //返回第一个元素,并在队列中删除
            for(String q : queue){
                System.out.println(q);
            }
            System.out.println("===");
            System.out.println("element="+queue.element()); //返回第一个元素 
            for(String q : queue){
                System.out.println(q);
            }
            System.out.println("===");
            System.out.println("peek="+queue.peek()); //返回第一个元素 
            for(String q : queue){
                System.out.println(q);
            }
        }
    }
    a
    b
    c
    d
    e
    ===
    poll=a
    b
    c
    d
    e
    ===
    element=b
    b
    c
    d
    e
    ===
    peek=b
    b
    c
    d
    e

    关于 Queue 是否是线程安全的问题: 

    这是一篇关于net的 Queue的 得到线程安全的处理方式: 参考:Queue 存入 和 取出 是线程安全的吗?

    Queue本身并不是线程安全的, 有两种方法来保证线程安全
    1. 手动加锁。
    Queue myCollection = new Queue();
    lock(myCollection.SyncRoot)
    {
        foreach (object item in myCollection)
        {
            // Insert your code here.
        }
    }
    2. 调用Synchronized方法,这时候得到的就是一个线程安全的Queue 
    Queue mySyncdQ = Queue.Synchronized( myQ );

    Java的原理大体相似,线程不安全;
  • 相关阅读:
    Spring boot 梳理
    Spring boot 梳理
    Spring boot 梳理
    观察者模式
    设计模式原则
    Spring MVC上传文件
    Spring MVC视图解析器
    Spring MVC中Action使用总结
    Spring MVC控制器
    Java并发 两个线程交替执行和死锁
  • 原文地址:https://www.cnblogs.com/aspirant/p/6796415.html
Copyright © 2011-2022 走看看