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. greenplum数据库常用操作

    1. 场景描述 greenplum集群部署好后,软件老王在实际使用过程中碰到一些问题,简单记录下,希望能帮到有需要的朋友. 2 .解决方案 2.1 gpcc监控地址 说明:非常重要,greenplum ...

  2. hdu3367最大伪森林(并查集)

    题目链接:http://icpc.njust.edu.cn/Problem/Hdu/3367/ 题目要求一个连通图的最大伪森林,伪森林是一个最多有一个回路的图.我们只要用Kruskal最大生成树的策略 ...

  3. 【视频+图文】Java经典基础练习题(三):输入3个整数,并将其由小到大输出

    目录 一.视频讲解 二.思路分析 总结: 三.代码+详解+结果 四.彩蛋 能解决题目的代码并不是一次就可以写好的 我们需要根据我们的思路写出后通过debug模式找到不足再进行更改 多次测试后才可得到能 ...

  4. 题解 P1748 【H数】

    我来讲讲 \(dp\) 的做法 前言 昨天 \(PHY\) 大佬问我,这题怎么做?考虑到他没学过 \(set\) . \(priority_queue\) 和 \(queue\) .之后,我就想到了可 ...

  5. Anomaly Detection-异常检测算法(Coursera-Ng-ML课程)

    现实生活中有许多需要提前预防一些异常问题出现的情况,例如在飞机起飞前,对飞机各部分进行评估,看发动机等各个零件是否性能正常,若有潜在的问题(可能出现异常情况),则需要及时检修或更换. 那么我们如何去评 ...

  6. layer弹层插件

      // 使用前需要引入jquery的支持,链接如下:   https://blog-static.cnblogs.com/files/liguanlong/jquery1.9.1.min.js    ...

  7. OpenCV-Python 特征匹配 | 四十四

    目标 在本章中, 我们将看到如何将一个图像中的特征与其他图像进行匹配. 我们将在OpenCV中使用Brute-Force匹配器和FLANN匹配器 Brute-Force匹配器的基础 蛮力匹配器很简单. ...

  8. 【WPF学习】第六十章 创建控件模板

    经过数十天的忙碌,今天终于有时间写博客. 前面一章通过介绍有关模板工作方式相关的内容,同时介绍了FrameWorkElement下所有控件的模板.接下来将介绍如何构建一个简单的自定义按钮,并在该过程中 ...

  9. coding++:java-Date日期转换工具类

    Code: package com.tree.ztree_demo.utils; import org.springframework.util.ObjectUtils; import java.te ...

  10. ANTLR随笔(三)

    ANTLR基本语法 前面已经简单介绍了ANTLR以及怎么安装和测试. 同学们应该大概清楚ANTLR的使用场景,但是对于关键步骤,怎么编写一个语法文件并没有详细介绍,这篇笔记主要详细讲解一下ANTLR的 ...