• 阻塞队列(BlockingQueue)


    概念

    • 首先它是一个队列,而一个阻塞队列在数据结构中所起的作用大致如图所示:

    • 当阻塞队列是空时,从队列中获取元素的操作将会被阻塞

    • 当阻塞队列是满时,往队列里添加元素的操作将会被阻塞

    核心方法

    • 抛异常:如果操作不能马上进行,则抛出异常

    • 特定的值:如果操作不能马上进行,将会返回一个特殊的值,一般是 true 或者 false

    • 阻塞:如果操作不能马上进行,操作会被阻塞

    • 超时:如果操作不能马上进行,操作会被阻塞指定的时间,如果指定时间没执行,则返回一个特殊值,一般是 true 或者 false

    实现类

     官方的7种实现:

    • ArrayBlockingQueue :一个由数组结构组成的有界阻塞队列,此队列按 FIFO(先进先出)对元素进行排序
    • LinkedBlockingQueue :一个由链表结构组成的有界阻塞队列,此队列按 FIFO(先进先出)对元素进行排序,吞吐量通常要高于ArrayBlockingQueue。此队列的默认和最大长度为 Integer.MAX_VALUE,可以认为是无界
    • PriorityBlockingQueue :一个支持优先级排序的无界阻塞队列
    • DelayQueue:一个使用优先级队列实现的无界阻塞队列
    • SynchronousQueue:一个不存储元素的阻塞队列,每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于LinkedBlokcingQueue
    • LinkedTransferQueue:一个由链表结构组成的无界阻塞队列
    • LinkedBlockingDeque:一个由链表结构组成的双向阻塞队列

     ArrayBlockingQueue 和LinkedBlockingQueue区别

    • 底层实现不同
      • ArrayBlockingQueue 底层使用数组来维护队列
      • LinkedBlockingQueue 底层使用链表来维护队列,在添加和删除队列中的元素的时候,会创建和销毁节点对象,在高并发和大量数据的时候,GC压力很大
    • 锁的方式不同
      • ArrayBlockingQueue 获取数据和添加数据都是使用同一个锁对象,不过,在ArrayBlockingQueue 中使用Condition的等待/通知机制,这样使得ArrayBlockingQueue的数据写入和获取操作已经足够轻巧,以至于引入独立的锁机制,除了给代码带来额外的复杂性外,其在性能上完全占不到任何便宜
      • LinkedBlockingQueue  获取数据和添加数据使用不同的锁对象

     SynchronousQueue

    实际上它不是一个真正的队列,因为它不会为队列中元素维护存储空间。与其他队列不同的是,它维护一组线程,这些线程在等待着把元素加入或移出队列

    public class SynchronousQueueDemo {
    
        public static void main(String[] args) {
            SynchronousQueue<Integer> synchronousQueue = new SynchronousQueue<>();
            new Thread(() -> {
                try {
                    synchronousQueue.put(1);
                    TimeUnit.SECONDS.sleep(3);
                    synchronousQueue.put(2);
                    TimeUnit.SECONDS.sleep(3);
                    synchronousQueue.put(3);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
    
            new Thread(() -> {
                try {
                    Integer val = synchronousQueue.take();
                    System.out.println(LocalDateTime.now().toString() + "---------" + val);
                    Integer val2 = synchronousQueue.take();
                    System.out.println(LocalDateTime.now().toString() + "---------" + val2);
                    Integer val3 = synchronousQueue.take();
                    System.out.println(LocalDateTime.now().toString() + "---------" + val3);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
    
    // 输出:
    // 2020-06-18T10:21:07.615---------1
    // 2020-06-18T10:21:10.496---------2
    // 2020-06-18T10:21:13.497---------3

    使用场景

    • 生产者消费者模式
    • 线程池
    • 消息中间件
  • 相关阅读:
    postgresql 添加触发器
    postgresql 操作
    postgresql 更新自增变量
    java8 stream api 文件流甚是牛逼
    fastjson妙用
    idea中springboot内置tomcat控制台中文乱码解决
    linux中开放某个端口
    idea中application.properties文件防止中文汉字自动转换成unicode编码解决办法
    使用vue开源项目vue-framework-wz遇到的问题以及解决方案
    rsync的使用
  • 原文地址:https://www.cnblogs.com/ding-dang/p/13156232.html
Copyright © 2020-2023  润新知