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的原理大体相似,线程不安全;
  • 相关阅读:
    ffmpeg rtmp推流 视频转码
    java日志发展史 log4j slf4j log4j2 jul jcl 日志和各种桥接包的关系
    nginx stream 流转发,可以转发rtmp、mysql访问流,转发rtmp、jdbc请求
    java web http 转https 通过nginx代理访问
    linux 服务器磁盘挂载
    novnc 通过websockify代理 配置多点访问
    linux 文件服务 minio 安装部署配置
    AOP实现原理,手写aop
    java 泛型
    JAVA反射getGenericSuperclass()用法
  • 原文地址:https://www.cnblogs.com/aspirant/p/6796415.html
Copyright © 2011-2022 走看看