精华内容
下载资源
问答
  • Java阻塞队列

    千次阅读 2018-07-24 16:05:40
    Java阻塞队列也是一种队列,只不过是实现了阻塞接口的队列。 public interface BlockingQueue<E> extends Queue<E>  在java.util.concurrent包中提供了五中实现阻塞接口的阻塞...

    1. 阻塞队列

     Java阻塞队列也是一种队列,只不过是实现了阻塞接口的队列。

    public interface BlockingQueue<E> extends Queue<E>

     在java.util.concurrent包中提供了五中实现阻塞接口的阻塞队列。它们实质上就是特殊一点的队列,各自如下所示:

    • ArrayBlockingQueue
    public class ArrayBlockingQueue<E> extends AbstractQueue<E>
            implements BlockingQueue<E>, java.io.Serializable

     基于数组的有界队列。

    • LinkedBlockingQueue
    public class LinkedBlockingDeque<E>
        extends AbstractQueue<E>
        implements BlockingDeque<E>, java.io.Serializable

     基于链表的无界队列。

    • PriorityBlockingQueue

     无界的优先级队列。

    public class PriorityBlockingQueue<E> extends AbstractQueue<E>
        implements BlockingQueue<E>, java.io.Serializable
    • DelayQueue

     优先级定时调度队列。

    public class DelayQueue<E extends Delayed> extends AbstractQueue<E>
        implements BlockingQueue<E>
    • SynchronousQueue

     没有数据缓冲的阻塞队列,即生产者和消费者互相等待对方,握手,然后一起离开。

    2. ArrayBlockingQueue与LinkedBlockingQueue区别

    2.1 ArrayBlockingQueue(数组阻塞队列)

     ArrayBlockingQueue是一个阻塞式的队列,继承自AbstractBlockingQueue,间接的实现了Queue接口和Collection接口。底层以数组的形式保存数据(实际上可看作一个有界数组)。

     常用的操作包括 add ,offer,put,remove,poll,take,peek。前三者add offer put 是插入的操作。后面四个方法是取出的操作。
    - add: 内部实际上调用的的offer方法,当Queue已经满了时,抛出一个异常。不会阻塞。

    • offer:当Queue已经满了时,返回false。不会阻塞。

    • put:当Queue已经满了时,会进入等待,只要不被中断,就会插入数据到队列中。会阻塞,可以响应中断。

     ArrayBlockingQueue的remove和add相互对应。调用remove方法时,如果队列为空,则抛出异常。

     poll与offer相互对应。take和put相互对应。

     peek方法比较特殊,前三个取出的方法,会将取到的元素顺便删除,而peek方法只是获取到队首元素,并不删除。peek方法也不会阻塞。当队列为空时,直接返回Null。

    2.2 对比LinkedBlockingQueue

     LinkedBlockingQueue同为阻塞队列,只是底层由链表实现,那么其与ArrayBlockingQueue的区别是什么呢?

     LinkedBlockingQueue保存元素是使用一个链表。其内部有一个Node的内部类,其中有一个属性 next,就这样形成了一个链表的结构。所以获取下一个元素,只要调用next就可以了。而ArrayBlockingQueue则是一个数组。

     LinkedBlockingQueue内部读写(插入获取)各有一个锁(读写锁),而ArrayBlockingQueue则读写共享一个锁。

    2.3 选择LinkedBlockingQueue还是ArrayBlockingQueue

     个人感觉大多数场景适合使用LinkedBlockingQueue。

     在JDK源码当中有说明,LinkedBlockingQueue比ArrayBlockingQueue有更高的吞吐量,但是性能表现更难预测(也就是说相比ArrayBlockingQueue性能表现不稳定,但是也很稳定了)。

     为什么会有吞吐量的区别,可能是LinkedBlockingQueue两个锁的缘故,在大量并发的情况下,插入和读取都很多时,ArrayBlockingQueue读写共用一个锁,阻塞时读写都不能进行,而LinkedBlockingQueue使用读写锁,读写任意阻塞不对另一个操作有影响。

     还有一点,因为ArrayBlockingQueue创建时,默认会直接创建一个Integer.MAX_VALUE的数组,当插入少,读取多时,就会造成很大的空间浪费。而LinkedBlockingQueue实际上实在等需要的时候才会创建一个Node节点。

    展开全文
  • Java 阻塞队列

    2016-07-14 17:20:53
    阻塞队列与普通队列的区别在于,当队列是空的时,从队列中获取元素的操作将会被阻塞,或者当队列是满时,往队列里添加元素的操作会被阻塞。试图从空的阻塞队列中获取元素的线程将会被阻塞,直到其他的线程往空的队列...

    阻塞队列与普通队列的区别在于,当队列是空的时,从队列中获取元素的操作将会被阻塞,或者当队列是满时,往队列里添加元素的操作会被阻塞。试图从空的阻塞队列中获取元素的线程将会被阻塞,直到其他的线程往空的队列插入新的元素。同样,试图往已满的阻塞队列中添加新元素的线程同样也会被阻塞,直到其他的线程使队列重新变得空闲起来,如从队列中移除一个或者多个元素,或者完全清空队列,下图展示了如何通过阻塞队列来合作:



    线程1往阻塞队列中添加元素,而线程2从阻塞队列中移除元素

    从5.0开始,JDK在java.util.concurrent包里提供了阻塞队列的官方实现。尽管JDK中已经包含了阻塞队列的官方实现,但是熟悉其背后的原理还是很有帮助的。

    阻塞队列的实现

    阻塞队列的实现类似于带上限的Semaphore的实现。下面是阻塞队列的一个简单实现

    public class BlockingQueue {
    
    private List queue = new LinkedList();
    
    private int  limit = 10;
    
    public BlockingQueue(int limit){
    
    this.limit = limit;
    
    }
    
    public synchronized void enqueue(Object item)
    
    throws InterruptedException  {
    
    while(this.queue.size() == this.limit) {
    
    wait();
    
    }
    
    if(this.queue.size() == 0) {
    
    notifyAll();
    
    }
    
    this.queue.add(item);
    
    }
    
    public synchronized Object dequeue()
    
    throws InterruptedException{
    
    while(this.queue.size() == 0){
    
    wait();
    
    }
    
    if(this.queue.size() == this.limit){
    
    notifyAll();
    
    }
    
    return this.queue.remove(0);
    
    }
    
    }
    

    必须注意到,在enqueue和dequeue方法内部,只有队列的大小等于上限(limit)或者下限(0)时,才调用notifyAll方法。如果队列的大小既不等于上限,也不等于下限,任何线程调用enqueue或者dequeue方法时,都不会阻塞,都能够正常的往队列中添加或者移除元素。

    展开全文
  • put方法在队列满时阻塞,take方法在队列空时阻塞。 * ArrayBlockingQueue在构造时需要指定容量 * * @param list */ private static void arrayBlockingQueue(List<String> list) { ArrayBlockingQueue&...
  • 主要介绍了Java 阻塞队列详解及简单使用的相关资料,需要的朋友可以参考下
  • 主要介绍了详解Java阻塞队列(BlockingQueue)的实现原理,阻塞队列是Java util.concurrent包下重要的数据结构,有兴趣的可以了解一下
  • 主要介绍了java阻塞队列实现原理及实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • java 阻塞队列的使用

    2019-04-04 16:41:51
    java 阻塞队列的使用

    java 阻塞队列的使用

    展开全文
  • java学习(基于Java阻塞队列的搜索实例).pdf
  • 主要介绍了Java阻塞队列四组API介绍,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • java阻塞队列与非阻塞队列

    千次阅读 2017-06-12 14:33:10
    在并发编程中,有时候需要使用线程安全的队列。如果要实现一个线程安全的队列有两种方式:一种是使用阻塞算法,另一种是使用非阻塞算法。...阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。这两个...

        在并发编程中,有时候需要使用线程安全的队列。如果要实现一个线程安全的队列有两种方式:一种是使用阻塞算法,另一种是使用非阻塞算法。

        //使用阻塞算法的队列可以用一个锁(入队和出队用同一把锁)或两个锁(入队和出队用不同的锁)等方式来实现。非阻塞的实现方式则可以使用循环CAS的方式来实现。

     

    阻塞队列:

    阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。这两个附加的操作支持阻塞的插入和移除方法。
    1)支持阻塞的插入方法:意思是当队列满时,队列会阻塞插入元素的线程,直到队列不满。
    2)支持阻塞的移除方法:意思是在队列为空时,获取元素的线程会等待队列变为非空。
    阻塞队列常用于生产者和消费者的场景,生产者是向队列里添加元素的线程,消费者是从队列里取元素的线程。阻塞队列就是生产者用来存放元素、消费者用来获取元素的容器。

    下表是阻塞队列的部分方法:

     

    方法\处理方式抛出异常返回特殊值一直阻塞超时退出
    插入方法add(e)offer(e)put(e)offer(e,time,unit)
    移除方法remove()poll()take()poll(time,unit)
    检查方法element()peek()不可用不可用
    • 抛出异常:是指当阻塞队列满时候,再往队列里插入元素,会抛出IllegalStateException(“Queue full”)异常。当队列为空时,从队列里获取元素时会抛出NoSuchElementException异常 。
    • 返回特殊值:插入方法会返回是否成功,成功则返回true。移除方法,则是从队列里拿出一个元素,如果没有则返回null
    • 一直阻塞:当阻塞队列满时,如果生产者线程往队列里put元素,队列会一直阻塞生产者线程,直到拿到数据,或者响应中断退出。当队列空时,消费者线程试图从队列里take元素,队列也会阻塞消费者线程,直到队列可用。
    • 超时退出:当阻塞队列满时,队列会阻塞生产者线程一段时间,如果超过一定的时间,生产者线程就会退出。

     

    JDK7提供了7个阻塞队列。分别是:

    • ArrayBlockingQueue :一个由数组结构组成的有界阻塞队列。
    • LinkedBlockingQueue :一个由链表结构组成的有界阻塞队列。
    • PriorityBlockingQueue :一个支持优先级排序的无界阻塞队列。
    • DelayQueue:一个使用优先级队列实现的无界阻塞队列。
    • SynchronousQueue:一个不存储元素的阻塞队列。
    • LinkedTransferQueue:一个由链表结构组成的无界阻塞队列。
    • LinkedBlockingDeque:一个由链表结构组成的双向阻塞队列。

     

    简单介绍下其中三个队列:

     

    SynchronousQueue

           SynchronousQueue是无界的,是一种无缓冲的等待队列,但是由于该Queue本身的特性,在某次添加元素后必须等待其他线程取走后才能继续添加;可以认为SynchronousQueue是一个缓存值为1的阻塞队列,但是 isEmpty()方法永远返回是true,remainingCapacity() 方法永远返回是0,remove()和removeAll() 方法永远返回是false,iterator()方法永远返回空,peek()方法永远返回null。
           声明一个SynchronousQueue有两种不同的方式,它们之间有着不太一样的行为。公平模式和非公平模式的区别:如果采用公平模式:SynchronousQueue会采用公平锁,并配合一个FIFO队列来阻塞多余的生产者和消费者,从而体系整体的公平策略;但如果是非公平模式(SynchronousQueue默认):SynchronousQueue采用非公平锁,同时配合一个LIFO队列来管理多余的生产者和消费者,而后一种模式,如果生产者和消费者的处理速度有差距,则很容易出现饥渴的情况,即可能有某些生产者或者是消费者的数据永远都得不到处理。

     

    LinkedBlockingQueue

           LinkedBlockingQueue默认大小是Integer.MAX_VALUE,可以设定大小,可以理解为一个缓存的有界等待队列。
           基于链表的阻塞队列,内部维持着一个数据缓冲队列(该队列由链表构成)。当生产者往队列中放入一个数据时,队列会从生产者手中获取数据,并缓存在队列内部,而生产者立即返回;只有当队列缓冲区达到最大值缓存容量时(LinkedBlockingQueue可以通过构造函数指定该值),才会阻塞生产者队列,直到消费者从队列中消费掉一份数据,生产者线程会被唤醒,反之对于消费者这端的处理也基于同样的原理。
           LinkedBlockingQueue之所以能够高效的处理并发数据,还因为其对于生产者端和消费者端分别采用了独立的锁来控制数据同步,这也意味着在高并发的情况下生产者和消费者可以并行地操作队列中的数据,以此来提高整个队列的并发性能。

     

    ArrayListBlockingQueue

           ArrayListBlockingQueue是有界的,是一个有界缓存的等待队列。
           基于数组的阻塞队列,同LinkedBlockingQueue类似,内部维持着一个定长数据缓冲队列(该队列由数组构成)。ArrayBlockingQueue内部还保存着两个整形变量,分别标识着队列的头部和尾部在数组中的位置。
           ArrayBlockingQueue在生产者放入数据和消费者获取数据,都是共用同一个锁对象,由此也意味着两者无法真正并行运行,这点尤其不同于LinkedBlockingQueue;按照实现原理来分析,ArrayBlockingQueue完全可以采用分离锁,从而实现生产者和消费者操作的完全并行运行。Doug Lea之所以没这样去做,也许是因为ArrayBlockingQueue的数据写入和获取操作已经足够轻巧,以至于引入独立的锁机制,除了给代码带来额外的复杂性外,其在性能上完全占不到任何便宜。 ArrayBlockingQueue和LinkedBlockingQueue间还有一个明显的不同之处在于,前者在插入或删除元素时不会产生或销毁任何额外的对象实例,而后者则会生成一个额外的Node对象。这在长时间内需要高效并发地处理大批量数据的系统中,其对于GC的影响还是存在一定的区别。

     

    非阻塞队列:

    ConcurrentLinkedQueue

            ConcurrentLinkedQueue是一个基于链接节点的无界线程安全队列,它采用先进先出的规则对节点进行排序,当我们添加一个元素的时候,它会添加到队列的尾部;当我们获取一个元素时,它会返回队列头部的元素。
            结构如下:

    public class ConcurrentLinkedQueue<E> extends AbstractQueue<E>  
            implements Queue<E>, java.io.Serializable {  
        private transient volatile Node<E> head;//头指针  
        private transient volatile Node<E> tail;//尾指针  
        public ConcurrentLinkedQueue() {//初始化,head=tail=(一个空的头结点)  
            head = tail = new Node<E>(null);  
        }  
        private static class Node<E> {  
            volatile E item;  
            volatile Node<E> next;//内部是使用单向链表实现  
            ......  
        }  
        ......  
    }  

     

            入队和出队操作均利用CAS(compare and set)更新,这样允许多个线程并发执行,并且不会因为加锁而阻塞线程,使得并发性能更好。

     

    以上~~

    展开全文
  • java阻塞队列是一个支持阻塞的插入,移除的队列。 阻塞的插入:向队列中插入元素时,若队满,则队列会阻塞插入的线程。 阻塞的移除:移除队列中的一个元素时,若队空,则队列会阻塞移除的线程。直至队列非空。从上...
  • 上一篇 细说并发4:Java 阻塞队列源码分析(上) 我们了解了 ArrayBlockingQueue, LinkedBlockingQueue 和 PriorityBlockingQueue,这篇文章来了解剩下的四种阻塞队列。读完本文你将了解:七种阻塞队列的后四种 ...
  • java阻塞队列的使用

    千次阅读 2020-04-24 23:57:12
    1.阻塞队列的作用 阻塞队列(BlockingQueue),顾名思义,首先它是一个队列,而一个阻塞队列在数据结构中所起的作用大致如图所示: 当阻塞队列是空时,从队列中获取元素的操作将会被阻塞 当阻塞队列是满时,往队列...
  • Java阻塞队列实现生产者消费者

    千次阅读 2018-04-10 10:31:46
    学习java阻塞队列 先要学习ReetrantLock 网址https://www.cnblogs.com/baizhanshi/p/6419268.htmlimport java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; public class test7...
  • Java阻塞队列之BlockingQueue

    千次阅读 2020-08-14 10:25:30
    阻塞队列的概念 当阻塞队列是空时,从队列中获取元素的操作将会被阻塞 当阻塞队列是满时,往队列里添加元素的操作将会被阻塞 ArrayBlockingQueue 数组组成的有界阻塞队列 代码示例:add、remove、element...
  • 先看看 BlockingQueue 接口的文档说明:  1、add:添加元素到队列里,添加成功返回true,由于容量满了添加失败会抛出 IllegalStateException 异常;...  6、take:删除队列头部元素,如果队列为空,一直阻塞队列
  • java阻塞队列以及非阻塞队列

    千次阅读 2014-04-16 23:44:43
    1.阻塞队列: submit(producer1);  executorService.submit(producer2);  executorService.submit(producer1);  Consumer consumer = new Consumer("consumer1");  executorServi
  • 阻塞队列:线程安全 按 FIFO(先进先出)排序元素。队列的头部 是在队列中时间最长的元素。队列的尾部 是在队列中时间最短的元素。新元素插入到队列的尾部,并且队列检索操作会获得位于队列头部的元素。链接...
  • 消息分发框架,基于java阻塞队列实现,生产者消费者模型 可用于任务分发,服务器消息消息,以及网络IO 性能优化,多线程
  • JAVA多线程19】JAVA 阻塞队列原理

    千次阅读 2019-06-13 00:39:08
    今天我们来讨论另外一类容器:阻塞队列。  非阻塞队列,比如PriorityQueue、LinkedList(LinkedList是双向链表,它实现了Dequeue接口)。  使用非阻塞队列的时候有一个很大问题就是:它不会对当前线程产生阻塞,...
  • 今天要来讲一下java里的队列队列,顾名思义,排队的列,既然按排队形来做的话,生活中的银行排队啊,上车排队啊,都是先到先办理或者先上车,队列存取数据元列也一样,这就是先进先出,使用队列的规则是:使用队素...
  • 文章目录阻塞队列消费者阻塞生产者阻塞插入操作获取数据操作 阻塞队列 队列是一种只允许在标的前端进行删除操作,而在表的藕断进行插入操作的线性表。阻塞队列和一班队列的不同之处在于阻塞队列是阻塞的,这里的阻塞...
  • Java阻塞队列的实现

    2014-10-09 12:02:14
    阻塞队列与普通队列的区别在于,当队列是空的时,从队列中获取元素的操作将会被阻塞,或者当队列是满时,往队列里添加元素的操作会被阻塞。试图从空的阻塞队列中获取元素的线程将会被阻塞,直到其他的线程往空的队列...
  • 解读 Java 并发队列 BlockingQueue 转自:https://javadoop.com/post/java-concurrent-queue 最近得空,想写篇文章好好说说 java 线程池问题,我相信很多人都一知半解的,包括我自己在仔仔细细看源码之前,也有...
  • java 阻塞队列实现生产者与消费者模式 public class BlockingTest { public static void main(String[] args) { ArrayBlockingQueue&lt;Integer&gt; arrayBlockingQueue = new ArrayBlockingQueue&...
  • Java 并发常用的组件中有一种队列叫阻塞队列(BlockingQueue),当队列为空时,获取元素的线程会阻塞等待直到队列有数据;当队列满时,想要存储元素的线程会阻塞等待直到队列有空间。我们经常会用这种数据结构可以...
  • 阻塞队列:线程安全 按 FIFO(先进先出)排序元素。队列的头部 是在队列中时间最长的元素。队列的尾部 是在队列中时间最短的元素。新元素插入到队列的尾部,并且队列检索操作会获得位于队列头部的元素。链接队列...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 179,427
精华内容 71,770
关键字:

java阻塞队列

java 订阅