(转自: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. set的运用 例题5-3 安迪的第一个字典(Andy's First Dictionary,Uva 10815)

    #include<bits/stdc++.h>using namespace std;set<string> dict;int main(){ string s, buf; w ...

  2. canal 整合RabbitMQ

    环境如下: canal: 1.15-alpha-1 mysql  5.6.49 rabbitmq 3.7.14 Erlang 21.3 canal 安装和启动 见上篇文章 canal快速安装启动 但是 ...

  3. docker19.03使用数据卷

    一,查看当前的docker版本 [root@localhost data]# docker --version Docker version 19.03.8, build afacb8b 说明:刘宏缔 ...

  4. 第二十四章 Find命令详细介绍

    一.Find 概述 可以根据文件的名称.文件大小.文件的修改时间.文件的类型.文件的权限.文件的属主属组.文件的目录层级进行查找 Find的语法: find [-H] [-L] [-P] [-Olev ...

  5. Unity-根据时间开灯与关灯

    声明:本人只是学生,并且只是自学Unity,如有大神,不喜勿喷,不足之处,请指出! 本项目使用了UniStorm 3.0(天气)插件,时间也是调用它本身的API,实际并不影响,用系统的时间的是也是可以 ...

  6. linux启动oracle服务 和监听

    (1) su - oracle 切换成oracle 用户 (2)sqlplus / as sysdba (3)startup: (4)quit:退出sql模式 exit 退出oracle用户 (5)l ...

  7. 01 . Go框架之Gin框架从入门到熟悉(路由和上传文件)

    Gin框架简介 Gin是使用Go/Golang语言实现的HTTP Web框架, 接口简洁, 性能极高,截止1.4.0版本,包含测试代码,仅14K, 其中测试代码9K, 也就是说测试源码仅5k左右, 具 ...

  8. vue自定义指令 默认图片

    /**  * 检测图片是否存在  * @param url  */ function imageIsExist(url) {     return new Promise((resolve) => ...

  9. 管理Pod(rc,rs,deployment)

    1.概述 可以把容器想像成豆荚里的豆子,把一个或多个关系紧密的豆子包在一起就是豆荚(一个Pod).在k8s中我们不会直接操作容器,而是把容器包装成Pod再进行管理. 2.管理Pod a. 使用Repl ...

  10. Django做验证码登录

    验证码 关注公众号"轻松学编程"了解更多. 1.作用 在用户登录,注册以及一些敏感操作的时候,我们为了防止服务器被暴力请求,或爬虫爬取,我们可以使用验证码进行过滤,减轻服务器的压力 ...