zoukankan      html  css  js  c++  java
  • 并发之 阻塞队列

    本节内容总结自《Java 并发编程的艺术》

    Java中的阻塞队列

    什么是阻塞队列
    1. 定义:阻塞队列是支持阻塞的插入和移除方法。支持阻塞的插入是指,当队列满时,队列会阻塞插入元素的线程,直到队列不满。支持阻塞的移除方法是指,队列为空时,获取元素的线程会等待队列变为非空。阻塞队列常用于生产者和消费者的场景,生产者是向队列中添加元素的线程,消费者是从队列中取元素的线程。

    2. 阻塞队列中提供的处理方式

      方法 抛出异常 返回特殊值 一直阻塞 超时退出
      插入方法 add(e) offer(e) put(e) offer(e, time, unit)
      移除方法 remove() poll() take() poll(time, unit)
      检查方法 element() peek() 不可用 不可用
    Java 中的阻塞队列
    1. ArrayBlockingQueue:是一个用数组实现的有界阻塞队列。按照插入顺序存储元素。默认情况下不保证线程公平的访问队列,为了保证公平性,可以在new时第二个参数使用true来创建一个公平性的队列。在该队列中,公平性是通过可重入锁ReentrantLock实现的。
    2. LinkedBlockingQueue:是一个用链表实现的有界阻塞队列。队列的默认和最大长度为Integer.MAX_VALUE。
    3. PriorityBlockingQueue:是一个支持优先级的无界阻塞队列。默认情况下采用升序排列。可以自定义类实现compareTo()方法来指定元素排序规则,或者初始化队列时,指定构造参数Comparator来对元素进行排序。
    4. DelayQueue:是一个支持延时获取元素的无界阻塞队列。队列使用PriorityQueue实现,队列中的元素必须实现Delayed接口,在创建元素时可以指定多久才能从队列中获取当前元素。只有在延迟期满时才能从队列中提取元素。
      • DelayQueue的使用场景
        1. 缓存系统的设计:可以用DelayQueue保存缓存元素的有效期,使用一个线程循环查询DelayQueue,一旦能从队列中过获取到元素,表示缓存有效期已经到了。
        2. 定时任务调度:使用DelayQueue保存当天将会执行的任务和执行时间,一旦从DelayQueue中获取到任务就开始执行。
    5. SynchronousQueue:是一个不存储元素的阻塞队列。每一个put操作必须等待一个take操作,否则不能继续添加元素。他支持公平访问队列(参数为true),默认情况下线程采用非公平性策略访问队列。SynchronousQueue可以看成是一个传球手,负责把生产者线程处理的数据直接传递给消费者线程。队列本身不存储任何元素,非常适合传递性场景。
    6. LinkedTransferQueue:是一个由链表结构组成的无界阻塞队列。相对于其他阻塞队列,LinkedTransferQueue队列多了transfer和tryTransfer方法。
      1. transfer方法:如果当前有消费者正在等待接收元素,transfer方法可以把生产者传入的元素立刻transfer给消费者。如果没有消费者在等待接收元素,transfer方法会将元素存放在队列的tail节点,并等待该元素被消费者消费了才返回。transfer方法会自旋等待消费者线程,但自旋一定次数之后也可以使用Thread.yield()方法来暂停自旋,并执行其他线程。
      2. tryTransfer方法:是用来试探生产者传入的元素是否能直接给消费者。如果没有消费者接收元素则返回false。和transfer方法的区别是,不论消费者是否存在,该方法都会立即返回。有时间限制的tryTransfer(E e, long timeout, TimeUnit unit)方法,试图把生产者传入的元素直接传给消费者,但是如果没有消费者消费该元素则等待指定时间再返回。
    7. LinkedBlockingDeque:是一个由链表结构组成的双向阻塞队列。它支持两端插入和删除元素。双向队列因为多了一个操作队列的入口和出口,在多线程同时入队时,也就减少了一般的竞争。
    阻塞队列的实现分析
    • 可以使用等待通知机制实现,就是当生产者往满的队列中插入元素时会阻塞住生产者,消费者消费了一个队列中的元素后会通知生产者停止阻塞。可以使用 Object类中的等待通知机制,或者 Condition实现。
    时间并不会因为你的迷茫和迟疑而停留,就在你看这篇文章的同时,不知道有多少人在冥思苦想,在为算法废寝忘食,不知道有多少人在狂热地拍着代码,不知道又有多少提交一遍又一遍地刷新着OJ的status页面…… 没有谁生来就是神牛,而千里之行,始于足下!
  • 相关阅读:
    利用python脚本统计和删除redis key
    利用expect交互完成多台linux主机ssh key推送
    iptables -L很慢的原因
    tomcat各个端口的作用
    rabbitmq集群搭建
    ping 没有回icmp reply
    go mod 无法下载依赖问题
    0/1 nodes are available: 1 node(s) had taint
    go 编译:build constraints exclude all Go files in
    k8s单机部署
  • 原文地址:https://www.cnblogs.com/bianjunting/p/14594687.html
Copyright © 2011-2022 走看看