Java提供两种方式来实现阻塞式和非阻塞式,阻塞式使用锁实现,非阻塞式使用CAS方式实现。使用阻塞队列和非阻塞队列的场景还有很多,比较常用的就是我们常说的生产者\消费者模型。 非阻塞队列 ConcurrentLinkedQueue——无界非阻塞队列 ? ? 阻塞队列 Java提供了一个阻塞队列的接口——BlockingQueue,在队列的基础上增加可阻塞添加元素和可阻塞获取元素的方法。 ? ? (oldCap + 2) : // grow faster if small (oldCap >> 1)); 当队列为空(或队列为满)时,消费者(或生产者)线程会进入阻塞状态,使用线程的阻塞/通知模型,来通知阻塞的线程。
2. 耦合,添加用户和增加积分,可以认为是两个领域,也 就是说,增加积分并不是注册必须要具备的功能,但是 一旦增加积分这个逻辑出现异常,就会导致注册失败。 所以其实如果把阻塞队 列比作成分布式消息队列的话,那么所谓的生产者和消费 者其实就是基于阻塞队列的解耦。 J.U.C 中的阻塞队列 J.U.C 提供的阻塞队列 在 Java8 中,提供了 7 个阻塞队列: ArrayBlockingQueue 数组实现的有界阻塞队列, 此队列按照先进先出(FIFO LinkedTransferQueue 链表实现的无界阻塞队列 LinkedBlockingDeque 链表实现的双向阻塞队列 阻塞队列的操作方法 在阻塞队列中,提供了四种处理方式 offer(e,time,unit) :当阻塞队列满了以后继续添加元素, 生产者线程会被阻塞指定时间,如果超时,则线程直接 退出 2.
生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力 这个阻塞队列就是用来给生产者和消费者解耦的。 阻塞队列是并发编程中的一个重要基础组件,帮助我们实现“生产者-消费者模型”(是一种典型的处理并发编程的模型) 如果入队列太快了,继续入队列就会阻塞,一直阻塞到有其他线程去消费队列了,才能继续入队列;如果出队列操作太快了 ,队列空了,也会阻塞,一直阻塞到没有其他线程生产了元素,才能继续出队列 阻塞队列也符合先进先出的规则 阻塞队列实现 //阻塞队列 public class ThreadDemo21 { static (入队列/出队列)(没有去队首元素操作) //1.阻塞版本的入队列 public void put(int value) throws InterruptedException
概述 BlockingQueue接口扩展了Queue接口,其中包含了阻塞操作,这意味着当队列为空或满时,某些操作将被阻塞。 2. 主要方法 2.1 放入元素 put(E e): 将指定的元素插入此队列,如果队列已满,则等待空间变为可用。 当队列满时,生产者线程将被阻塞,直到有空间可用;当队列为空时,消费者线程将被阻塞,直到有元素可用。 当队列满时,生产者线程将被阻塞,直到有空间可用;当队列为空时,消费者线程将被阻塞,直到有元素可用。 它是一个直接传输的阻塞队列,意味着插入操作会阻塞直到另一个线程调用移除操作,反之亦然。
学数据结构时学过队列,特点是FIFO,先进先出。那么什么阻塞队列呢?一起来看看。 一、什么是阻塞队列? 阻塞队列,英文名BlockingQueue,顾名思义,首先它是一个队列。 当一个线程从阻塞队列中取元素时,如果队列为空了,那么取元素的操作就会被阻塞,直到有其他线程往队列中添加了元素;当一个线程往阻塞队列中添加元素时,如果队列满了,那么添加元素的操作也会被阻塞,直到有其他线程从队列中取走了元素 二、为什么要用阻塞队列? 有了阻塞队列,我们不需要关心何时阻塞线程,何时唤醒线程。因为这些操作阻塞队列都帮我们做了。队列为空那么取元素的线程会自动被阻塞,队列已满那么添加元素的线程会自动阻塞。 五、阻塞队列用在哪? 1、用在哪? 阻塞队列有哪些应用呢?常见的有以下三个: 生产消费模式; 线程池; 消息中间件。 本文将讲解生产消费模式中如何使用阻塞队列。 阻塞队列版生产消费模式 这就是阻塞队列版的生产消费模式,不用我们去控制线程的通信。
什么是阻塞队列 原文地址为,转载请注明出处! 阻塞队列是一个支持阻塞的插入和移除的队列。 支持阻塞的插入方法:意思是当队列满时,队列会阻塞插入元素的线程,直到队列不满。 支持阻塞的移除方法:意思是队列为空时,获取元素(同时移除元素)的线程会被阻塞,等到队列变为非空。 阻塞队列用法 阻塞队列常用于生产者和消费者的场景,生产者是向队列里添加元素的线程,消费者是从队列里获取元素的线程。 如果是移除方法,则是从队列中取出一个元素,没有则返回null。 一直阻塞:当阻塞队列满时,如果生产者线程往队列里面put元素,则生产者线程会被阻塞,知道队列不满或者响应中断退出。 ReentrantLock(fair); notEmpty = lock.newCondition(); notFull = lock.newCondition(); } 2.
默认情况下不保证线程公平地访问队列。 那么什么是安全?可以查看之前这篇文章 公平访问就是指阻塞的所有生产者线程或消费者线程,当队列可用时,可以按照阻塞的先后顺序访问队列。 即先阻塞的线程,先被唤醒。 LinkedBlockingQueue 使用链表的阻塞队列,和ArrayListBlockingQueue一样遵循先进先出(FIFO)的原则排序。 当生产者往队列中放入一个数据时,队列会从生产者手中获取数据,并缓存在队列内部,而生产者立即返回;只有当队列缓冲区达到缓存容量的最大值时(构造方法指定缓冲区容量),才会阻塞生产者队列,直到消费者从队列中消费掉一份数据 所以如果没有指定缓冲区容量大小的话生产者的速度大于消费者的速度,也许还没有等到队列满阻塞产生,内存就已经被消耗完了。 PriorityBlockingQueue 支持优先级的无界队列。 DelayQueue 延时获取元素的无界阻塞队列。队列使用PriorityQueue来实现。队列中的元素必须实现 Delayed 接口。
BlockingQueue 是一个接口,意思是这个队列在放入元素或者取出元素的过程中允许阻塞。 存入元素时,如果没有剩余容量则会阻塞,取出元素时,如果队列为空则会阻塞。 在任何给定的时间,它都可能有一个剩余容量,超过这个容量,任何额外的元素都不能在不被阻塞的情况下放置。 BlockingQueue实现主要用于生产者-消费者队列,但额外支持集合接口。因此,例如,可以使用remove(x)从队列中删除任意元素。 e.printStackTrace(); } } }); thread1.start(); Thread thread2 e.printStackTrace(); } } }); thread2.
BlockingQueue 阻塞队列(BlockingQueue) 是一个支持两个附加操作的队列。这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空。 当队列满时,存储元素的线程会等待队列可用。阻塞队列常用于生产者和消费者的场景,生产者是往队列里添加元素的线程,消费者是从队列里拿元素的线程。 可以是限定容量的 超过给定容量时是无法添加的 JDK中七个队列 ArrayBolckingQueue(常用):基于数组的有界阻塞队列 LinkedBlockingQueue(常用):基于链表的有界阻塞队列 DelayQueue: 使用优先级队列实现的延迟无界阻塞队列 SynchronousQueue: 一个不存储元素的阻塞队列。 LinkedBlockingDeque: 一个由链表结构组成的双向阻塞队列 阻塞队列核心方法 方法类型 抛出异常 特殊值( 有返回值) 阻塞 超时 插入 add offer put offer 移除 remove
ArrayBlockingQueue 是一个用数组实现的有界阻塞队列。此队列按照先进先出(FIFO)的原则对元素进行排序。 默认情况下不保证访问者公平的访问队列,所谓公平访问队列是指阻塞的所有生产者线程或消费者线程,当队列可用时,可以按照阻塞的先后顺序访问队列,即先阻塞的生产者线程,可以先往队列里插入元素,先阻塞的消费者线程 ,可以先从队列里获取元素。 主要常量 /** 队列元素数组 */ final Object[] items; /** 队列头部元素的索引位置 */ int takeIndex; /** 队列尾部元素的索引位置 */ int putIndex 生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力
,产生阻塞 locker.wait(); } elems[tail] = elem; tail + ,产生阻塞 } elem = elems[head]; head ++; if (head >= elems.length , 唤醒 } return elem; } } 1.通过"循环队列" 的方式来实现 2. 使用 synchronized 进行加锁控制. 3.put 插⼊元素的时候, 判定如果队列满了, 就进⾏ wait. (注意, 要在循环中进⾏ wait 被唤醒时不⼀定 队列就不满了,因为同时可能是唤醒了多个线程). 4. take 取出元素的时候, 判定如果队列为空, 就进⾏ wait. (也是循环 wait).
一、阻塞队列 ---- 【1】首先它是一个队列,而一个阻塞队列在数据结构中所起的作用大致如下图所示: ? 二、架构分析 ---- 【1】阻塞队列的架构图:阻塞队列与 List 具有很多类似之处,对比着学习会更加容易一些。 ? 【2】阻塞队列重点子类说明: ■ ArrayBlockingQueue:由数组结构组成的有界阻塞队列。 :当阻塞队列满时,生产者继续向队列中 put 元素,队列会一直阻塞生产线程直到 put 数据或者响应中断。 当阻塞队列为空时,消费者线程试图从队列中 take 元素,队列会一直阻塞消费者线程直到队列可用。
什么是阻塞队列? 阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。 这两个附加的操作是: 在队列为空时,获取元素的线程会等待队列变为非空。 阻塞队列就是生产者存放元素的容器,而消费者也只从容器里拿元素。 JDK7 提供了7 个阻塞队列。分别是: ArrayBlockingQueue:一个由数组结构组成的有界阻塞队列。 LinkedBlockingQueue:一个由链表结构组成的有界阻塞队列。 PriorityBlockingQueue:一个支持优先级排序的无界阻塞队列。 DelayQueue:一个使用优先级队列实现的无界阻塞队列。 SynchronousQueue:一个不存储元素的阻塞队列。 LinkedTransferQueue:一个由链表结构组成的无界阻塞队列。 LinkedBlockingDeque:一个由链表结构组成的双向阻塞队列。 阻塞队列的实现原理是什么?
之前看到 ArrayBlockQueue 的实现,感觉挺有意思的,自己也实现一个阻塞队列,通过等待通知的方式,直接上代码 package thread; import java.util.LinkedList import java.util.concurrent.locks.ReentrantLock; /** * @author shengjk1 * @date 2020/11/4 */ // 实现一个阻塞队列 System.out.println(c.get()); } ; }, "c" + i).start(); } try { TimeUnit.SECONDS.sleep(2) } catch (InterruptedException e) { e.printStackTrace(); } // //启动生产者线程 for (int i = 0; i < 2;
【2】阻塞添加:当阻塞队列是满时,往队列里添加元素的操作将被阻塞。 【3】阻塞移除:当阻塞队列是空时,从队列中获取元素/删除元素的操作将被阻塞。 2)支持阻塞的移除方法take: 队列空时,获取元素的线程会等待队列变为非空。 true,如果队列已满,返回false(不阻塞) (2)offer(E e, long timeout, TimeUnit unit):可以设置阻塞时间,如果队列已满,则进行阻塞 实现阻塞最重要的两个方法是 take 方法和 put 方法。 2)take 方法 take 方法的功能是获取并移除队列的头结点,通常在队列里有数据的时候是可以正常移除的。 过程如图所示: 【2】是否有界 阻塞队列还有一个非常重要的属性,那就是容量的大小,分为有界和无界两种。
本文转发自:https://blog.csdn.net/u012881904/article/details/51491736 阻塞队列与普通队列的区别在于,当队列是空的时,从队列中获取元素的操作将会被阻塞 ,或者队列是满时,往队列里添加元素的操作会被阻塞。 试图从空的阻塞队列中获取元素的线程将会被阻塞,直到其他的线程往空的队列插入新的元素。 同样,试图往已满的阻塞队列中添加新元素的线程同样也会被阻塞,直到其他的线程使队列重新变得空闲起来,如从队列中移除一个或者多个元素,或者完全清空队列. 1.ArrayDeque, (数组双端队列) 2. , (基于链表的FIFO双端阻塞队列) 8.PriorityBlockingQueue, (带优先级的无界阻塞队列) 9.SynchronousQueue (并发同步阻塞队列) 阻塞队列和生产者-消费者模式
在python中,提供了线程安全的阻塞队列queue。这使得对信号量的需求降低了不少。能很简单的实现生产消费者模式。 下面是一个例子,实现两个阻塞队列,并且对它们同时进行监听取数据。 queue from multiprocessing.dummy import Pool as ThreadPool import time q1 = queue.Queue(maxsize=0) q2 ())) def test_insert(): for i in range(10): q1.put(i) time.sleep(0.1) q2. put(i) p = ThreadPool(4) p.apply_async(monitor, (q1,)) p.apply_async(monitor, (q2,)) p.apply_async(test_insert
前言 今天讲阻塞队列,阻塞队列有很多,这篇文章只讲解ArrayBlockingQueue,其他的大同小异。 阻塞队列常用于生产者和消费者的场景,生产者是往队列里添加元素的线程,消费者是从队列里拿元素的线程。阻塞队列就是生产者存放元素的容器,而消费者也只从容器里拿元素。 阻塞队列有哪些? PriorityBlockingQueue:以上2种队列都是先进先出队列,而PriorityBlockingQueue却不是,它会按照元素的优先级对元素进行排序,按照优先级顺序出队,每次出队的元素都是优先级最高的元素 注意,此阻塞队列为无界阻塞队列,即容量没有上限(通过源码就可以知道,它没有容器满的信号标志),前面2种都是有界队列。 ; CountDownLatch countDownLatch = new CountDownLatch(2); for (int i = 1; i <= 2; i++)
但是有了阻塞队列就不一样了,它会对当前线程产生阻塞,比如一个线程从一个空的阻塞队列中取元素,此时线程会被阻塞直到阻塞队列中有了元素。 一.几种主要的阻塞队列 二.阻塞队列中的方法 VS 非阻塞队列中的方法 三.阻塞队列的实现原理 四.示例和使用场景 若有不正之处请多多谅解,并欢迎批评指正。 PriorityBlockingQueue:以上2种队列都是先进先出队列,而PriorityBlockingQueue却不是,它会按照元素的优先级对元素进行排序,按照优先级顺序出队,每次出队的元素都是优先级最高的元素 注意,此阻塞队列为无界阻塞队列,即容量没有上限(通过源码就可以知道,它没有容器满的信号标志),前面2种都是有界队列。 2.阻塞队列中的几个主要方法: 阻塞队列包括了非阻塞队列中的大部分方法,上面列举的5个方法在阻塞队列中都存在,但是要注意这5个方法在阻塞队列中都进行了同步措施。
阻塞队列 BlockingQueue 队列主要有两种:FIFO(先进先出)、LIFO(后进先出)。 ArrayBlockingQueue 基于数组实现的有界阻塞安全线程队列。 LinkedBlockingQueue 基于链表实现的阻塞队列 构造函数 public LinkedBlockingQueue() { this(Integer.MAX_VALUE); private transient volatile int allocationSpinLock; //扩容时,CAS更新这个值谁更新成功谁执行 private PriorityQueue<E> q;//不阻塞的优先队列 * * 2.