(转自:https://blog.csdn.net/wei_ya_wen/article/details/19344939 侵删)

在java多线程操作中, BlockingQueue<E> 常用的一种方法之一。在看jdk内部尤其是一些多线程,大量使用了blockinkQueue 来做的。

借用jdk api解释下:

BlockingQueue 方法以四种形式出现,对于不能立即满足但可能在将来某一时刻可以满足的操作,这四种形式的处理方式不同:第一种是抛出一个异常,第二种是返回一个特殊值(null 或 false,具体取决于操作),第三种是在操作可以成功前,无限期地阻塞当前线程,第四种是在放弃前只在给定的最大时间限制内阻塞。下表中总结了这些方法:

  抛出异常 特殊值 阻塞 超时
插入 add(e) offer(e) put(e) offer(e, time, unit)
移除 remove() poll() take() poll(time, unit)
检查 element() peek() 不可用 不可用

offer: 将指定元素插入此队列中(如果立即可行且不会违反容量限制),成功时返回 true,如果当前没有可用的空间,则返回 false,不会抛异常:

java源代码

[html] view plain copy
  1. public boolean offer(E e) {
  2. if (e == null) throw new NullPointerException();
  3. final ReentrantLock lock = this.lock;
  4. lock.lock();
  5. try {
  6. if (count == items.length)
  7. return false;
  8. else {
  9. insert(e);
  10. return true;
  11. }
  12. } finally {
  13. lock.unlock();
  14. }
  15. }

put:

将指定元素插入此队列中,将等待可用的空间.通俗点说就是>maxSize 时候,阻塞,直到能够有空间插入元素

java源代码:

[html] view plain copy
  1. public void put(E e) throws InterruptedException {
  2. if (e == null) throw new NullPointerException();
  3. final E[] items = this.items;
  4. final ReentrantLock lock = this.lock;
  5. lock.lockInterruptibly();
  6. try {
  7. try {
  8. while (count == items.length)
  9. notFull.await();
  10. } catch (InterruptedException ie) {
  11. notFull.signal(); // propagate to non-interrupted thread
  12. throw ie;
  13. }
  14. insert(e);
  15. } finally {
  16. lock.unlock();
  17. }
  18. }

take: 获取并移除此队列的头部,在元素变得可用之前一直等待 。queue的长度 == 0 的时候,一直阻塞

java 源代码:

[html] view plain copy
  1. public E take() throws InterruptedException {
  2. final ReentrantLock lock = this.lock;
  3. lock.lockInterruptibly();
  4. try {
  5. try {
  6. while (count == 0)
  7. notEmpty.await();
  8. } catch (InterruptedException ie) {
  9. notEmpty.signal(); // propagate to non-interrupted thread
  10. throw ie;
  11. }
  12. E x = extract();
  13. return x;
  14. } finally {
  15. lock.unlock();
  16. }
  17. }

add: 和collection的add一样,没什么可以说的。如果当前没有可用的空间,则抛出 IllegalStateException



例子如下:

[html] view plain copy
  1. public static void main(String[] args) {
  2. java.util.concurrent.Executor executor = Executors.newFixedThreadPool(10);
  3. Runnable task = new Runnable() {
  4. @Override
  5. public void run() {
  6. System.out.println("ggg");
  7. }
  8. };
  9. executor.execute(task);
  10. */
  11. BlockingQueue q = new ArrayBlockingQueue(10);
  12. Producer p = new Producer(q);
  13. Consumer c1 = new Consumer(q);
  14. Consumer c2 = new Consumer(q);
  15. new Thread(p).start();
  16. new Thread(c1).start();
  17. new Thread(c2).start();
  18. }
  19. }
  20. class Producer implements Runnable {
  21. private final BlockingQueue<Object> queue;
  22. Producer(BlockingQueue q) { queue = q; }
  23. public void run() {
  24. for(int i=0;i<100;i++){
  25. try {
  26. queue.put(i);
  27. } catch (InterruptedException e1) {
  28. // TODO Auto-generated catch block
  29. e1.printStackTrace();
  30. }
  31. try {
  32. Thread.sleep(20);
  33. } catch (InterruptedException e) {
  34. // TODO Auto-generated catch block
  35. e.printStackTrace();
  36. }
  37. }
  38. }
  39. }
  40. class Consumer implements Runnable {
  41. private final BlockingQueue queue;
  42. Consumer(BlockingQueue q) { queue = q; }
  43. public void run() {
  44. try {
  45. while(true) {
  46. consume(
  47. queue.take()
  48. );
  49. }
  50. } catch (InterruptedException ex) {
  51. }
  52. }
  53. void consume(Object x) {
  54. System.out.println(x);
  55. }
  56. }

BlockingQueue中 take、offer、put、add的一些比较的更多相关文章

  1. 多线程之BlockingQueue中 take、offer、put、add的一些比较

    一.概述: BlockingQueue作为线程容器,可以为线程同步提供有力的保障.   二.BlockingQueue定义的常用方法 1.BlockingQueue定义的常用方法如下:   抛出异常 ...

  2. Dockerfile 中的 COPY 与 ADD 命令

    Dockerfile 中提供了两个非常相似的命令 COPY 和 ADD,本文尝试解释这两个命令的基本功能,以及其异同点,然后总结其各自适合的应用场景. Build 上下文的概念 在使用 docker ...

  3. 【Docker】涨姿势,深入了解Dockerfile 中的 COPY 与 ADD 命令

    参考资料:https://www.cnblogs.com/sparkdev/p/9573248.html Dockerfile 中提供了两个非常相似的命令 COPY 和 ADD,本文尝试解释这两个命令 ...

  4. 【转载】C#中ArrayList集合类使用Add方法添加元素

    ArrayList集合是C#中的一个非泛型的集合类,是弱数据类型的集合类,可以使用ArrayList集合变量来存储集合元素信息,任何数据类型的变量都可加入到同一个ArrayList集合中,因此使用Ar ...

  5. docker(11)Dockerfile 中的COPY与ADD 命令

    前言 Dockerfile 中提供了两个非常相似的命令 COPY 和 ADD,本文尝试解释这两个命令的基本功能,以及其异同点,然后总结其各自适合的应用场景. Build 上下文的概念 在使用 dock ...

  6. java源码研究--List中的set和add方法区别

    在处理一道题目是,发现他们使用了List 中的set 方法,这个方法我平时很少用到,今天来研究一下,set和add的区别 add(int index,Object obj)方法与set(int ind ...

  7. oracle11.2中分区功能测试之add&amp;split partition对global&amp;local index的影响

    生产库中某些大表的分区异常,需要对现有表进行在线操作,以添加丢失分区,因为是生产库,还是谨慎点好,今天有空,针对add&split分区对global&local索引的影响进行了测试,测 ...

  8. 记录 Java 的 BlockingQueue 中的一些坑

    最近学习了 BlockingQueue,发现 java 的 BlockingQueue 并不是每一个实现都按照 BlockingQueue 的语意来的,其中有不少坑. 直接上代码吧: 1.关于Prio ...

  9. [学习笔记] 在Eclipse中添加用户库 Add User Libraries ,在项目中引用用户库

    如果还没有安装Eclipse, 则请参考前文:  [学习笔记] 下载.安装.启动 Eclipse(OEPE) 添加用户库 本文主要介绍在项目中直接使用第三方库的情况.就是把第三方的jar文件直接放到某 ...

随机推荐

  1. MeteoInfoLab脚本示例:站点数据散点图

    这里演示从micaps第一类数据(地面全要素观测)中读取一个变量(用DimDataFile类的stationdata方法),然后maskout掉中国区域之外的数据,利用scatterm函数绘制散点图. ...

  2. IDEA项目路径初探

    IDEA项目路径 普通Java项目 普通Java项目,标准目录结构src下的路径就是classpath类路径,每次编译都会将src目录下新增的类和资源文件打包进类路径. 如下图,类文件和配置文件都会被 ...

  3. Shell Scripting 笔记

    Shell Scripting Tutorial Variables in the Bourne shell do not have to be declared, as they do in lan ...

  4. 【博弈论】51Nod 1534 棋子游戏

    题目内容 波雷卡普和瓦西里喜欢简单的逻辑游戏.今天他们玩了一个游戏,这个游戏在一个很大的棋盘上进行,他们每个人有一个棋子.他们轮流移动自己的棋子,波雷卡普先开始.每一步移动中,波雷卡普可以将他的棋子从 ...

  5. lvs搭建dr负载均衡集群

    一,查看本地centos的版本: [root@localhost lib]# cat /etc/redhat-release CentOS Linux release 8.1.1911 (Core) ...

  6. 运行shell文件时提示/bin/bash^M: bad interpreter: 没有那个文件

    查看脚本文件是dos格式还是unix格式的几种办法.(1)cat -A filename 从显示结果可以判断,dos格式的文件行尾为^M$,unix格式的文件行尾为$:(2)od -t x1 file ...

  7. salesforce零基础学习(九十六)项目中的零碎知识点小总结(四)

    本篇参考: https://developer.salesforce.com/docs/atlas.en-us.216.0.apexcode.meta/apexcode/apex_classes_ke ...

  8. 第十三章 nginx代理服务

    一.数据库迁移 1.常见原因 1.数据库要做升级2.数据库服务器到期需要迁移 2.新服务器搭建数据库 [root@db02 ~]# yum install -y mariadb-server 3.启动 ...

  9. CPU 底层运算之乘法运算

    CPU 运算加减法运算 假设计算  3+3  原码是0011 * 0011(以4位存贮单元,因为是原码,最高位不代表符号位) 1. 首先 判断 两个加数是否有 负数(减法)  如果有 负数 先将负数转 ...

  10. spring-boot-route(二十一)quartz实现动态定时任务

    Quartz是一个定时任务的调度框架,涉及到的主要概念有以下几个: Scheduler:调度器,所有的调度都由它控制,所有的任务都由它管理. Job:任务,定义业务逻辑. JobDetail:基于Jo ...