Java提供两种方式来实现阻塞式和非阻塞式,阻塞式使用锁实现,非阻塞式使用CAS方式实现。使用阻塞队列和非阻塞队列的场景还有很多,比较常用的就是我们常说的生产者\消费者模型。...非阻塞队列 ConcurrentLinkedQueue——无界非阻塞队列 ? ?...,当有入队时则会唤醒阻塞的出队操作线程;当队列满时,进行入队操作的线程将被阻塞,当有出队时则会唤醒阻塞的入队操作线程。...;出队不仅需要唤醒满队列时入队阻塞的线程,还需要唤醒空队列出队的线程。...当队列为空(或队列为满)时,消费者(或生产者)线程会进入阻塞状态,使用线程的阻塞/通知模型,来通知阻塞的线程。
前言 " JUC 下面的相关源码继续往下阅读,这就看到了非阻塞的无界线程安全队列 —— ConcurrentLinkedQueue,来一起看看吧。..." 1 介绍 基于链接节点的无界线程安全队列,对元素FIFO(先进先出)进行排序。队列的头部是队列中最长时间的元素,队列的尾部是队列中最短时间的元素。...在队列的尾部插入新元素,队列检索操作获取队列头部的元素。 当许多线程共享对公共集合的访问 ConcurrentLinkedQueue 是一个合适的选择。...queue.peek(); // 获取并移除此队列的头,此队列为空返回 null。...简单总结就是使用单向链表来保存队列元素,内部使用非阻塞的 CAS 算法,没有加锁。所以计算 size 时可能不准确,同样 size 会遍历链表,所以并不建议使用。 - -
试图从空的阻塞队列中获取元素的线程将会被阻塞,直到其他的线程往空的队列插入新的元素。...同样,试图往已满的阻塞队列中添加新元素的线程同样也会被阻塞,直到其他的线程使队列重新变得空闲起来,如从队列中移除一个或者多个元素,或者完全清空队列. 1.ArrayDeque, (数组双端队列) 2....一个线程的失败或挂起不应该影响其他线程的失败或挂起,这样的算法成为非阻塞(nonblocking)算法;如果算法的每一个步骤中都有一些线程能够继续执行,那么这样的算法称为锁自由(lock-free)算法...在线程间使用CAS进行协调,这样的算法如果能构建正确的话,它既是非阻塞的,又是锁自由的。非竞争的CAS总是能够成功,如果多个线程以一个CAS竞争,总会有一个胜出并前进。...非阻塞算法堆死锁和优先级倒置有“免疫性”(但它们可能会出现饥饿和活锁,因为它们允许重进入)。 非阻塞算法通过使用低层次的并发原语,比如比较交换,取代了锁。
自己写一个阻塞队列 阻塞队列,主要操作有两个,一个是put放入元素,另一个是take取出元素。所谓的阻塞就是当多个线程同时存取数据时,如果遇到队列为空或者队列为满时,会发生阻塞。...如果正常存入了元素,那么唤醒其他阻塞的线程(有些执行take操作的线程因为队列为空而阻塞) take: 从队列中取一个元素,如果队列为空,则阻塞当前线程,等待唤醒。...如果正常取出了元素,那么唤醒其他阻塞的线程(有些执行put操作的线程因为队列满而阻塞) Object类提供了几个操作来进行当前线程的唤醒和阻塞。...而且上面介绍提到的唤醒部分,每当成功put或者成功take,我们都唤醒所有线程,其实put操作成功时,我们只想唤醒那些因为队列为空而阻塞的线程,take操作成功时,我们只想唤醒那些因为队列已满而阻塞的线程...首先,提供了put和take对应的非阻塞方法offer和poll,这两个方法,即使遇到队列为满或为空的情况,也不会阻塞当前线程,而是直接返回false或null。
阻塞队列 BlockingQueue 队列主要有两种:FIFO(先进先出)、LIFO(后进先出)。...再多线程环境中,队列很容实现数据共享,我们常用的"生产者"、"消费者"模型就可以通过队列来传递数据达到数据共享。...但是现实中,大多数情况都是生产者产生消息的速度和消费的速度是不匹配的,就需要相应的对生产或者消费进行阻塞。当生产的消息积累到一定程度时,就需要对生产者就行阻塞,以便消费者将积累的消息进行消费。...BlockingQueue释放了我们的双手,他让我们不用关系什么时候去阻塞,什么时候去唤醒线程。...ArrayBlockingQueue 基于数组实现的有界阻塞安全线程队列。
1.0 非阻塞队列 在上篇中,我们讲到了阻塞队列,以及阻塞队列中的几个实现类。 本篇,我们继续对队列进行研究。而今天的主题,则是非阻塞队列!...在非阻塞队列中,ConcurrentLinkedQueue是主要代表。 之前,我们了解了什么是阻塞队列,在此我们再简单地回顾下! 什么是阻塞队列?...阻塞,顾名思义:当我们的生产者向队列中生产数据时,若队列已满,那么生产线程会暂停下来,直到队列中有可以存放数据的地方,才会继续工作;而当我们的消费者向队列中获取数据时,若队列为空,则消费者线程会暂停下来...这就是阻塞队列。 那么,非阻塞队列又是什么含义呢? 什么是非阻塞队列? 与阻塞队列相反,非阻塞队列的执行并不会被阻塞,无论是消费者的出队,还是生产者的入队。...在底层,非阻塞队列使用的是CAS(compare and set)来实现线程执行的非阻塞。 非阻塞队列的操作 与阻塞队列相同,非阻塞队列中的常用方法,也是出队和入队。
一、 前言 常用的并发队列有阻塞队列和非阻塞队列,前者使用锁实现,后者则使用CAS非阻塞算法实现,使用非阻塞队列一般性能比较好,下面就看看常用的非阻塞ConcurrentLinkedQueue是如何使用...= null; p = succ(p)) { E item = p.item; //相等则使用cas值null,同时一个线程成功,失败的线程循环查找队列中其他元素是否有匹配的...10.1 Acceptor线程 accept线程作用是接受客户端发来的连接请求并放入到事件队列。 ?...十二、总结 ConcurrentLinkedQueue使用CAS非阻塞算法实现使用CAS解决了当前节点与next节点之间的安全链接和对当前节点值的赋值。...所以要保证队列线程安全只需要保证对这两个Node操作的可见性和原子性,由于volatile本身保证可见性,所以只需要看下多线程下如果保证对着两个变量操作的原子性。
两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空。当队列满时,存储元素的线程会等待队列可用。...阻塞队列常用于生产者和消费者的场景,生产者是往队列里添加元素的线程,消费者是从队列里拿元素的线程。阻塞队列就是生产者存放元素的容器,而消费者也只从容器里拿元素。...常见阻塞场景 当队列中没有数据的情况下,消费者端的所有线程都会被自动堵塞(挂起),直到有数据放入队列。...当队列中填满数据的情况下,生产者端的所有线程都会被自动阻塞(挂起),直到队列中有空的位置,线程被自动唤醒。 支持以上两种阻塞场景的被称为阻塞队列。...公平访问队列就是指阻塞的所有生产者线程或消费线程,当队列可用是,可以按照阻塞的先后顺序访问队列。即先阻塞的生产者线程,可以先往队列里插入元素;先阻塞的消费者线程,可以先从队列里获取元素 。
ConcurrentLinkedQueue实现原理 上文,笔者介绍了非阻塞队列的基础知识,对于其代表类ConcurrentLinkedQueue做了个简单阐述。...在Node中,item表示元素,next为指向下一个元素的指针,并且都被volatitle所修饰。 之前,我们说了ConcurrentLinkedQueue是使用CAS来实现非阻塞入队出队。...volatitlte是一个轻量级的同步机制,当有线程对其所修饰的属性进行更新时,被更新的值会立刻同步到内存中去,并且使其他cpu所缓存的值置为无效。当其他线程对该属性操作时,必须从主存中获取。...: 当插入的元素为空时候,会抛出异常,禁止向队列中插入尾空元素; 创建插入元素的新结点newNode,从tail指针处遍历链表结构。...此处需要注意,由于是插入队列的第一个元素,所以需要回过去看下队列的默认构造是如何实现。
正如上篇文章聊聊 JDK 阻塞队列源码(ReentrantLock实现)所说,队列在我们现实生活中队列随处可见,最经典的就是去银行办理业务,超市买东西排队等。...主要方法源码实现 add:添加元素到队列里,添加成功返回true; offer:添加元素到队列里,添加成功返回true,添加失败返回false; put:添加元素到队列里,如果容量满了会阻塞直到容量不满...否则返回元素; take:删除队列头部元素,如果队列为空,一直阻塞到队列有元素并删除。...是一个基于链接节点的无界线程安全队列,它采用先进先出的规则对节点进行排序,当我们添加一个元素的时候,它会添加到队列的尾部,当我们获取一个元素时,它会返回队列头部的元素。...,如果p的next为null,说明p是尾节点,casNext返回true; // 如果p的next不为null,说明有其他线程更新过队列的尾节点,casNext返回false
一、LinkedBlockingDeque简介 在多线程阻塞队列的应用中上一篇已经讲述了ArrayBlockingQueue,在这一篇主要介绍思想与他差不多的另一个阻塞队列,基于链表的阻塞队列-...基于链表的阻塞队列和基于数组的阻塞队列相同,内部都有一把可重入锁,对于该队列的写操作和读操作都会进行加锁,所以他们都是线程安全的,但是写操作和读操作都会占用锁资源所以在并发量大的情况下会降低性能。...new ReentrantLock(); //非空条件 - 取出元素时会因为队列为空而阻塞 private final Condition notEmpty = lock.newCondition();...//非满条件 - 放入元素时会因为队列容量满了而阻塞 private final Condition notFull = lock.newCondition(); · 构造函数 //未指定队列最大容量大小...将原尾结点的下一个结点指向新插入的节点 l.next = node; //当前容量增加 ++count; //唤醒读取时因队列中无元素而导致阻塞的线程 notEmpty.signal
final ReentrantLock putLock = new ReentrantLock(); //非满条件 下文中会提到 当进行写操作时如果队列元素已满,会阻塞 private final Condition...0,这一步的写操作需要唤醒读操作 signalNotEmpty(); return true; } //这个方法与put方法相比,不会阻塞线程,队列满则直接返回。...第二个方法指定了阻塞超时时间,超过了阻塞超时时间或被唤醒则停止阻塞,继续执行。第三个方法不会阻塞,当读取失败则直接返回。 可以对比看出,读线程的锁操作与写线程的锁操作类似。...他也是线程安全的阻塞队列,阻塞条件为读操作时如果队列为空则阻塞、写操作时如果队列满则阻塞。...他们在读操作遇到队列为空或者写操作队列为满时都会阻塞线程。 (3)构造函数不同,LinkedBlockingQueue可以指定最大容量的小或者不指定,不指定时他的容量大小为最大值。
阻塞队列 阻塞队列是什么?...阻塞队列(BlockingQueue)是一种特殊的队列,它也是遵循“先进先出”的原则; 其中,它有俩个重要的特性: 当队列满的时候,继续入队列会阻塞,直到其他线程从队列中取走元素 当队列空的时候,继续出队列会阻塞...,直到其他线程从队列中插入元素 阻塞队列一个典型的应用场景就是“生产者消费者模型”,这是一种典型的开发模型; 生产者消费者模型 生产者和消费者通过一个容器(这个容器可以是很多种数据结构)可以解决消费者和生产者之间的强耦合关系...,导致宕机;这个时候将这些请求加入到阻塞队列中,可以让消费者慢慢的去处理阻塞队列中的请求,以防服务器被这一波大的请求直接冲垮~ 2.进行解耦合 在以下场景: 过年一个人进行包饺子,一般会有明确的分工...其中put方法和take方式是带有阻塞行为的入队列和出队列,而之前像offer方法或poll方法是不带阻塞行为的方法~ import java.util.concurrent.ArrayBlockingQueue
在Java并发包中提供了两种类型的队列,非阻塞队列与阻塞队列,当然它们都是线程安全的,无需担心在多线程并发环境所带来的不可预知的问题。为什么会有非阻塞和阻塞之分呢?...这里的非阻塞与阻塞在于有界与否,也就是在初始化时有没有给它一个默认的容量大小,对于阻塞有界队列来讲,如果队列满了的话,则任何线程都会阻塞不能进行入队操作,反之队列为空的话,则任何线程都不能进行出队操作。...而对于非阻塞无界队列来讲则不会出现队列满或者队列空的情况。它们俩都保证线程的安全性,即不能有一个以上的线程同时对队列进行入队或者出队操作。 ...非阻塞队列:ConcurrentLinkedQueue 阻塞队列:ArrayBlockingQueue、LinkedBlockingQueue、…… 本文介绍非阻塞队列——ConcurentLinkedQueue...每次即tail->next = newNode;tail = newNode;这样在单线程环境来确实没问题,但是,在多线程并发环境下就不得不要考虑线程安全,每次更新tail节点意味着每次都要使用CAS更新
言归正传,这一段时间我的工作主要是改进公司的调度器,调度器调度线程池执行任务,生产者生产任务,消费者消费任务,那么这时就需要一个任务队列,生产者向队列里插入任务,消费者从队列里提取任务执行,调度器里是通过...ArrayBlockQueue:一个由数组支持的有界阻塞队列。此队列按 FIFO(先进先出)原则对元素进行排序。创建其对象必须明确大小,像数组一样。 2....LinkedBlockQueue:一个可改变大小的阻塞队列。此队列按 FIFO(先进先出)原则对元素进行排序。创建其对象如果没有明确大小,默认值是Integer.MAX_VALUE。...链接队列的吞吐量通常要高于基于数组的队列,但是在大多数并发应用程序中,其可预知的性能要低。 3. ...10个取鸡蛋线程,前5个放入鸡蛋的线程成功执行,到第6个,发现盘子满了,阻塞住,这时切换到取鸡蛋线程执行,成功实现了生产者/消费者模式。
· 有界队列,初始化时需要指定的队列容量,就是该队列的最大容量,队列中容量达到最大值时不会扩容,则会阻塞队列。...boolean fair为true时采用公平锁,线程获取锁的顺序会和线程调用lock获取锁的顺序一样,但是公平锁需要增加阻塞和唤醒的时间开销。...添加操作完成后,还会唤醒因元素为空无法获取元素而阻塞住的线程。另外放入元素后队列容量达到最大值时,会重置putIndex的位置为0。...(); } 在这个元素中比较有意思的是用了notFull和NotEmpty监控用于线程的阻塞与唤醒。...notFull.signal()可以唤醒因队列空间满而无法将元素放入数组导致阻塞的线程,notEmpty()可以唤醒因队列空间无数据而无法取出数组中的元素导致阻塞的线程。
老习惯,还是先跟各位纸上谈会儿兵,首先说说队列,他主要分为并发队列和阻塞队列,在多线程业务场景中使用最为普遍,我就主要结合我所做过的业务谈谈我对它们的看法,关于它们的API和官方解释就不提了。...并发队列 并发队列:最常见的业务场景就是多个线程共享同一个队列中的所有资源,就拿我们公司的业务场景来说,当用户通过多个渠道下单后,然后就会有多个不同的客户端通道同时去获取订单并处理订单,为了加快订单处理速度我们使用并发队列来充当任务源头...并发队列没什么可说的,就是一个简单的多线程编程操作,小Demo送给各位: 1 /** 2 * 并发队列ConcurrentLinkedQueue的使用 3 */ 4 5 public...,消费者不断从阻塞队列中获取任务;当阻塞队列中填满数据时,所有生产者端的线程自动阻塞,当阻塞队列中数据为空时,所有消费端的线程自动阻塞。...阻塞队列的一些常用方法 ?
我们可能都已经听过阻塞非阻塞的概念,本文以tcp中的connect系统调用为例子(基于1.12.13内核,新版的原理类似,但是过程就很复杂了,有时间再分析),分析阻塞和非阻塞是什么并且看他是如何实现的。...sync包,然后根据socket的属性(阻塞非阻塞,可以通过setsocketopt设置)做下一步处理,如果是非阻塞,那么就比较简单,直接返回给应用层。...add_wait_queue就是把一个节点插入队列。我们看看wait_queue的定义。...这就是进程阻塞的原理,主要是两个过程 1 加入等待队列 2 让出CPU,调度其他进程执行。 我们这个进程什么时候被唤醒呢?我们从收到sync的回包开始分析。具体逻辑在tcp_rcv中。...另外我们看到,这里这是修改进程为可执行状态,但是不会立刻调度,要等下一次进程调度的时候才发生进程调度。以上就是进程阻塞和非阻塞的原理。
非阻塞并发队列ConcurrentLinkedQueue概述 我们之前花了很多时间了解学习BlockingQueue阻塞队列接口下的各种实现,也大概对阻塞队列的实现机制有了一定的了解:阻塞 + 队列嘛。...,采用CAS非阻塞算法,自旋到一定程度呢,才采取阻塞,比如:SynchronousQueue、LinkedTransferQueue等等,原理上是基于CAS原子指令提供的轻量级多线程同步机制。...并没有实现BlockingQueue接口,是一个完完全全使用CAS操作实现线程安全的、无界的非阻塞队列。...非阻塞算法就是这样,通过循环CAS的方式利用CPU资源来替代阻塞线程的资源消耗。...总结 ConcurrentLinkedQueue是一个使用CAS操作实现线程安全的、无界的非阻塞队列,基于链表。
:耗费着系统资源….对于非阻塞模式的socket该函数会马上返回,然后告诉你:WSAEWOULDDBLOCK—“现在没有数据,回头在来看看” 扩展: 在进行网络编程时,我们常常见到同步、异步、阻塞和非阻塞四种调用方式...如果是使用通知的方式,效率则很高,因为执行部件几乎不需要做额外的操作。至于回调函数,其实和通知 没太多区别。 阻塞 阻塞调用是指调用结果返回之前,当前线程会被挂起。...socket接收数据的另外一个函数recv则是一个阻塞调用的例子。当socket工作在阻塞模式的时候, 如果没有数据的情况下调用该函数,则当前线程就会被挂起,直到有数据为止。...非阻塞 非阻塞和阻塞的概念相对应,指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回。...阻塞对象上可以有非阻塞的调用方式,我们可以通过一定的API去轮询状态,在适当的时候调用阻塞函数,就可以避免阻塞。而对于非阻塞对象,调用特殊的函数也可以进入阻塞调用。
领取专属 10元无门槛券
手把手带您无忧上云