BlockingQueue接口定义了一种阻塞的FIFO queue,每一个BlockingQueue都有一个容量,让容量满时往BlockingQueue中添加数据时会造成阻塞,当容量为空时取元素操作会阻塞。

ArrayBlockingQueue是一个由数组支持的有界阻塞队列。在读写操作上都需要锁住整个容器,因此吞吐量与一般的实现是相似的,适合于实现“生产者消费者”模式。

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

ArrayBlockingQueue和LinkedBlockingQueue的区别:

1. 队列中锁的实现不同

ArrayBlockingQueue实现的队列中的锁是没有分离的,即生产和消费用的是同一个锁;

LinkedBlockingQueue实现的队列中的锁是分离的,即生产用的是putLock,消费是takeLock

2. 在生产或消费时操作不同

ArrayBlockingQueue实现的队列中在生产和消费的时候,是直接将枚举对象插入或移除的;

LinkedBlockingQueue实现的队列中在生产和消费的时候,需要把枚举对象转换为Node<E>进行插入或移除,会影响性能

3. 队列大小初始化方式不同

ArrayBlockingQueue实现的队列中必须指定队列的大小;

LinkedBlockingQueue实现的队列中可以不指定队列的大小,但是默认是Integer.MAX_VALUE

  1. public class BlockingQueueTest {
  2. private static ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(5, true); //最大容量为5的数组堵塞队列
  3. //private static LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<Integer>(5);
  4. private static CountDownLatch producerLatch; //倒计时计数器
  5. private static CountDownLatch consumerLatch;
  6. public static void main(String[] args) {
  7. BlockingQueueTest queueTest = new BlockingQueueTest();
  8. queueTest.test();
  9. }
  10. private void test(){
  11. producerLatch = new CountDownLatch(10); //state值为10
  12. consumerLatch = new CountDownLatch(10); //state值为10
  13. Thread t1 = new Thread(new ProducerTask());
  14. Thread t2 = new Thread(new ConsumerTask());
  15. //启动线程
  16. t1.start();
  17. t2.start();
  18. try {
  19. System.out.println("producer waiting...");
  20. producerLatch.await(); //进入等待状态,直到state值为0,再继续往下执行
  21. System.out.println("producer end");
  22. } catch (InterruptedException e) {
  23. e.printStackTrace();
  24. }
  25. try {
  26. System.out.println("consumer waiting...");
  27. consumerLatch.await(); //进入等待状态,直到state值为0,再继续往下执行
  28. System.out.println("consumer end");
  29. } catch (InterruptedException e) {
  30. e.printStackTrace();
  31. }
  32. //结束线程
  33. t1.interrupt();
  34. t2.interrupt();
  35. System.out.println("end");
  36. }
  37. //生产者
  38. class ProducerTask implements Runnable{
  39. private Random rnd = new Random();
  40. @Override
  41. public void run() {
  42. try {
  43. while(true){
  44. queue.put(rnd.nextInt(100)); //如果queue容量已满,则当前线程会堵塞,直到有空间再继续
  45. //offer方法为非堵塞的
  46. //queue.offer(rnd.nextInt(100), 1, TimeUnit.SECONDS); //等待1秒后还不能加入队列则返回失败,放弃加入
  47. //queue.offer(rnd.nextInt(100));
  48. producerLatch.countDown(); //state值减1
  49. //TimeUnit.SECONDS.sleep(2); //线程休眠2秒
  50. }
  51. } catch (InterruptedException e) {
  52. //e.printStackTrace();
  53. }  catch (Exception ex){
  54. ex.printStackTrace();
  55. }
  56. }
  57. }
  58. //消费者
  59. class ConsumerTask implements Runnable{
  60. @Override
  61. public void run() {
  62. try {
  63. while(true){
  64. Integer value = queue.take(); //如果queue为空,则当前线程会堵塞,直到有新数据加入
  65. //poll方法为非堵塞的
  66. //Integer value = queue.poll(1, TimeUnit.SECONDS); //等待1秒后还没有数据可取则返回失败,放弃获取
  67. //Integer value = queue.poll();
  68. System.out.println("value = " + value);
  69. consumerLatch.countDown(); //state值减1
  70. TimeUnit.SECONDS.sleep(2); //线程休眠2秒
  71. }
  72. } catch (InterruptedException e) {
  73. //e.printStackTrace();
  74. } catch (Exception ex){
  75. ex.printStackTrace();
  76. }
  77. }
  78. }
  79. }

ArrayBlockingQueue和LinkedBlockingQueue的使用的更多相关文章

  1. ArrayBlockingQueue跟LinkedBlockingQueue的区别

    .队列中的锁的实现不同 ArrayBlockingQueue中的锁是没有分离的,即生产和消费用的是同一个锁: LinkedBlockingQueue中的锁是分离的,即生产用的是putLock,消费是t ...

  2. ArrayBlockingQueue和LinkedBlockingQueue分析

        JAVA并发包提供三个常用的并发队列实现,分别是:ConcurrentLinkedQueue.LinkedBlockingQueue和ArrayBlockingQueue. Concurren ...

  3. JDK源码分析—— ArrayBlockingQueue 和 LinkedBlockingQueue

    JDK源码分析—— ArrayBlockingQueue 和 LinkedBlockingQueue 目的:本文通过分析JDK源码来对比ArrayBlockingQueue 和LinkedBlocki ...

  4. ArrayBlockingQueue和LinkedBlockingQueue的区别

    ArrayBlockingQueue和LinkedBlockingQueue的区别,得出结论如下: 1. 队列中锁的实现不同 ArrayBlockingQueue实现的队列中的锁是没有分离的,即生产和 ...

  5. Java 容器源码分析之ArrayBlockingQueue和LinkedBlockingQueue

    Java中的阻塞队列接口BlockingQueue继承自Queue接口. BlockingQueue接口提供了3个添加元素方法. add:添加元素到队列里,添加成功返回true,由于容量满了添加失败会 ...

  6. ArrayBlockingQueue和LinkedBlockingQueue

    1.BlockingQueue接口定义了一种阻塞的FIFO queue ArrayBlockingQueue和LinkedBlockingQueue的区别: 1. 队列中锁的实现不同 ArrayBlo ...

  7. ArrayBlockingQueue,LinkedBlockingQueue分析

    BlockingQueue接口定义了一种阻塞的FIFO queue,每一个BlockingQueue都有一个容量,让容量满时往BlockingQueue中添加数据时会造成阻塞,当容量为空时取元素操作会 ...

  8. 20.并发容器之ArrayBlockingQueue和LinkedBlockingQueue实现原理详解

    1. ArrayBlockingQueue简介 在多线程编程过程中,为了业务解耦和架构设计,经常会使用并发容器用于存储多线程间的共享数据,这样不仅可以保证线程安全,还可以简化各个线程操作.例如在“生产 ...

  9. java并发编程(二十四)----(JUC集合)ArrayBlockingQueue和LinkedBlockingQueue介绍

    这一节我们来了解阻塞队列(BlockingQueue),BlockingQueue接口定义了一种阻塞的FIFO queue,每一个BlockingQueue都有一个容量,当容量满时往BlockingQ ...

随机推荐

  1. kerberos系列之zookeeper的认证配置

    本篇博客介绍配置zookeeper的kerberos配置 一.zookeeper安装 1.解压安装包和重命名和创建数据目录 tar -zxvf /data/apache-zookeeper-3.5.5 ...

  2. Natas10 Writeup(正则表达式、grep命令)

    Natas10: 页面与上一关类似,只是增加了提示“出于安全原因,我们现在过滤某些字符”. 查看源码,发现关键代码如下: $key = ""; if(array_key_exist ...

  3. thinkPHP渗透之经验决定成败

    如上图,目标就一个登陆框,最近 Thinkphp 程序很多,根据后台地址结构,猜测可能是 ThinkPHP ,随手输入 xxx 得到 thinkPHP 报错页面,确定目标程序和版本. 然后上 5.X ...

  4. 原创 记录一次线上Mysql慢查询问题排查过程

    背景 前段时间收到运维反馈,线上Mysql数据库凌晨时候出现慢查询的报警,并把原始sql发了过来: --去除了业务含义的sql update test_user set a=1 where id=1; ...

  5. canvas绘制流星雨特效

    源码: <!DOCTYPE html><html> <head> <meta charset="utf-8"> <meta n ...

  6. Symantec(赛门铁克)非受管检测

    为了查找局域网内没有安装赛门铁克客户端的IP,采用Symantec Endpoint Protect Manager 的非受管检测机制进行网段扫描. 非受管检测机制的原理是:每台电脑开机时都会向同网段 ...

  7. u库前戏

    u库 ORM:对象关系映射 类 >>> 数据库的一张表 对象 >>> 表的一条记录 对象点属性 >>> 记录某一个字段对应的值 ''' 对象就是一 ...

  8. 【bug】table重新加载数据,页面滚动条下沉到底部,记录scrollTop后将其恢复scrollTop出现闪烁

    1.table数据请求前记录scrollTop $scope.scrollPos = document.documentElement.scrollTop; 2.html中添加指令repeat-fin ...

  9. 为什么你的程序配了classpath还是找不到类

    classpath简介 classpath是java程序时拥有的一个系统变量,这个变量可以通过如下方式获取 System.out.println(System.getProperty("ja ...

  10. c++源文件从文本阶段到可执行文件的过程

    过程分为四个阶段: 预处理阶段····>编译阶段····>汇编阶段····>链接阶段 1)预处理阶段:对源代码文件中的文件包含关系.预编译语句(宏定义)进行分析和替换,生成预编译文件 ...