BlockingQueue

BlockingQueue、解决了多线程中,如何高效安全“传输”数据的问题。程序员无需关心什么时候阻塞线程,什么时候唤醒线程,该唤醒哪个线程。

方法介绍



BlockingQueue是Queue的子类

void put(E e)

插入指定元素,当BlockingQueue为满,则线程阻塞,进入Waiting状态,直到BlockingQueue有空闲空间再继续。

这里以ArrayBlockingQueue为例进行分析



void take()

队首出队,当BlockingQueue为空,则线程阻塞,进入Waiting状态,直到BlockingQueue不为空再继续。



int drainTo(Collection<? super E> c)

从队列中批量取出数据,并放入到另一个集合中,返回转移数据的数量,只需一次加锁和解锁。

BlockingQueue的实现类

ArrayBlockingQueue

  1. /*
  2. * Concurrency control uses the classic two-condition algorithm
  3. * found in any textbook.
  4. */
  5. /** Main lock guarding all access */
  6. final ReentrantLock lock;
  7. /** Condition for waiting takes */
  8. private final Condition notEmpty;
  9. /** Condition for waiting puts */
  10. private final Condition notFull;

基于数组实现的BlockingQueue,需要指定队列容量,可以指定是否为公平锁;只有一个ReentrantLock,生产者和消费者不能异步执行。

LinkedBlockingQueue

  1. /** Lock held by take, poll, etc */
  2. private final ReentrantLock takeLock = new ReentrantLock();
  3. /** Wait queue for waiting takes */
  4. private final Condition notEmpty = takeLock.newCondition();
  5. /** Lock held by put, offer, etc */
  6. private final ReentrantLock putLock = new ReentrantLock();
  7. /** Wait queue for waiting puts */
  8. private final Condition notFull = putLock.newCondition();

基于链表实现的BlockingQueue,可以指定队列容量,不指定队列容量默认为Integer.MAX_VALUE;有两个ReentrantLock,生产者和消费者可以异步执行。

BlockingQueue实现生产者消费者模型

  • 缓冲区可以存放大量数据
  • 生产者和消费者速度各不相同
  1. public class MyThread42 {
  2. public static void main(String[] args)
  3. {
  4. final BlockingQueue<String> bq = new ArrayBlockingQueue<String>(10);
  5. Runnable producerRunnable = new Runnable()
  6. {
  7. int i = 0;
  8. public void run()
  9. {
  10. while (true)
  11. {
  12. try
  13. {
  14. System.out.println("我生产了一个" + i++);
  15. bq.put(i + "");
  16. Thread.sleep(1000);
  17. }
  18. catch (InterruptedException e)
  19. {
  20. e.printStackTrace();
  21. }
  22. }
  23. }
  24. };
  25. Runnable customerRunnable = new Runnable()
  26. {
  27. public void run()
  28. {
  29. while (true)
  30. {
  31. try
  32. {
  33. System.out.println("我消费了一个" + bq.take());
  34. Thread.sleep(3000);
  35. }
  36. catch (InterruptedException e)
  37. {
  38. e.printStackTrace();
  39. }
  40. }
  41. }
  42. };
  43. Thread producerThread = new Thread(producerRunnable);
  44. Thread customerThread = new Thread(customerRunnable);
  45. producerThread.start();
  46. customerThread.start();
  47. }
  48. }

输出结果如下

  1. 我生产了一个0
  2. 我消费了一个1
  3. 我生产了一个1
  4. 我生产了一个2
  5. 我消费了一个2
  6. 我生产了一个3
  7. 我生产了一个4
  8. 我生产了一个5
  9. 我消费了一个3
  10. 我生产了一个6
  11. 我生产了一个7
  12. 我生产了一个8
  13. 我消费了一个4
  14. 我生产了一个9
  15. 我生产了一个10
  16. 我生产了一个11
  17. 我消费了一个5
  18. 我生产了一个12
  19. 我生产了一个13
  20. 我生产了一个14
  21. 我消费了一个6
  22. 我生产了一个15
  23. 我生产了一个16
  24. 我消费了一个7
  25. 我生产了一个17
  26. 我消费了一个8
  27. 我生产了一个18
  28. 我消费了一个9
  29. 我生产了一个19
  30. 我消费了一个10
  31. 我生产了一个20
  32. 我消费了一个11
  33. 我生产了一个21
  34. 我消费了一个12
  35. 我生产了一个22
  36. 我消费了一个13
  37. 我生产了一个23
  38. 我消费了一个14
  39. 我生产了一个24
  40. ······

生产者没有生产到BlockingQueue的容量(极限是10)之前,生产3个,消费1个,再生产到BlockingQueue的容量之后,生产一个消费一个,因为不能超过BlockingQueue的容量。

Java多线程(十):BlockingQueue实现生产者消费者模型的更多相关文章

  1. Java多线程15:Queue、BlockingQueue以及利用BlockingQueue实现生产者/消费者模型

    Queue是什么 队列,是一种数据结构.除了优先级队列和LIFO队列外,队列都是以FIFO(先进先出)的方式对各个元素进行排序的.无论使用哪种排序方式,队列的头都是调用remove()或poll()移 ...

  2. Java阻塞队列(BlockingQueue)实现 生产者/消费者 示例

    Java阻塞队列(BlockingQueue)实现 生产者/消费者 示例 本文由 TonySpark 翻译自 Javarevisited.转载请参见文章末尾的要求. Java.util.concurr ...

  3. 多线程学习-基础(十二)生产者消费者模型:wait(),sleep(),notify()实现

    一.多线程模型一:生产者消费者模型   (1)模型图:(从网上找的图,清晰明了) (2)生产者消费者模型原理说明: 这个模型核心是围绕着一个“仓库”的概念,生产者消费者都是围绕着:“仓库”来进行操作, ...

  4. java 多线程并发系列之 生产者消费者模式的两种实现

    在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题.该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度. 为什么要使用生产者和消费者模式 在线程世界里,生产者就是生产数据 ...

  5. Java 多线程学习笔记:生产者消费者问题

    前言:最近在学习Java多线程,看到ImportNew网上有网友翻译的一篇文章<阻塞队列实现生产者消费者模式>.在文中,使用的是Java的concurrent包中的阻塞队列来实现.在看完后 ...

  6. 【Java并发编程】:生产者—消费者模型

    生产者消费者问题是线程模型中的经典问题:生产者和消费者在同一时间段内共用同一存储空间,生产者向空间里生产数据,而消费者取走数据. 这里实现如下情况的生产--消费模型: 生产者不断交替地生产两组数据“姓 ...

  7. Java多线程之并发协作生产者消费者设计模式

    两个线程一个生产者个一个消费者 需求情景 两个线程,一个负责生产,一个负责消费,生产者生产一个,消费者消费一个 涉及问题 同步问题:如何保证同一资源被多个线程并发访问时的完整性.常用的同步方法是采用标 ...

  8. java多线程系列15 设计模式 生产者 - 消费者模式

    生产者-消费者 生产者消费者模式是一个非常经典的多线程模式,比如我们用到的Mq就是其中一种具体实现 在该模式中 通常会有2类线程,消费者线程和生产者线程 生产者提交用户请求 消费者负责处理生产者提交的 ...

  9. Java多线程—阻塞队列和生产者-消费者模式

    阻塞队列支持生产者-消费者这种设计模式.该模式将“找出需要完成的工作”与“执行工作”这两个过程分离开来,并把工作项放入一个“待完成“列表中以便在随后处理,而不是找出后立即处理.生产者-消费者模式能简化 ...

随机推荐

  1. SQL-W3School-高级:SQL LIKE 操作符

    ylbtech-SQL-W3School-高级:SQL LIKE 操作符 1.返回顶部 1. LIKE 操作符用于在 WHERE 子句中搜索列中的指定模式. LIKE 操作符 LIKE 操作符用于在 ...

  2. HTM概述

    Html: Hyper Text Markup Language 超文本标记语言 超文本: 超出纯文本的范畴 标记语言: 标记其实就是标签 标签的格式: <标签名称>

  3. [Java读书笔记] Effective Java(Third Edition) 第 5 章 泛型

    第 26 条:请不要使用原生态类型 声明中具有一个或多个类型参数的类或者接口,就是泛型(generic). 例如List接口只有单个类型参数E, 表示列表的元素类型.这个接口全称List<E&g ...

  4. Redis的各项功能解决了哪些问题?(转)

    http://www.cnblogs.com/linianhui/p/what-problem-does-redis-solve.html 先看一下Redis是一个什么东西.官方简介解释到:Redis ...

  5. 不要在viewWillDisappear:方法中移除通知

    都知道viewWillAppear:方法是在控制器的view将要显示的时候调用的,而viewWillDisappear:方法是在控制器的view将要隐藏的时候调用. 这看上去没什么问题,键盘的显示和隐 ...

  6. java处理jqueryGantt甘特图数据的task.depends依赖规则方法

    前端采用jqueryGantt,github地址为:https://github.com/robicch/jQueryGantt 原以为后端只需要简单地保存甘特图任务列表和返回任务列表就行了. 但功能 ...

  7. Flutter之ExpansionTile组件

    ExpansionTile组件 ExpansionTile Widget就是一个可以展开闭合的组件,常用的属性有如下几个. title:闭合时显示的标题,这个部分经常使用Text Widget. le ...

  8. 阅读随笔 Spring、Mybatis

    一.<Spring+Mybatis 企业应用实战>(第2版本) 本书讲解了Spring.Mybatis及Spring+MyBatis 工作中的常用方法,没有太深入的原理性讲解,介绍 “如何 ...

  9. Hyperledger Fabric 常用命令

    Peer常用命令: #peer chaincode --help #peer channel list --help --logging-level <string> #<strin ...

  10. 01.04 linux命令(2

    ======================Linux下的用户管理==============用户信息保存/etc/passwd ,一般用户都有读的权限真正的用户:修改密码,可以登录伪用户:应用程序在 ...