ArrayBlockingQueue take()和poll()等方法的小区别

最近工作中看见一个同事的代码是关于ArrayBlockingQueue方面的使用,然后引出take()和poll()的小小的区别,当然他实现方式是没有错.但是由于选择不当有性能的开销,所以我想这里整理一下关于ArrayBlockingQueue
的理解,纯技术交流.有不正确的地方请谅解.下面对源码做一个导读.首先

ArrayBlockingQueue是一个基于数组、先进先出、线程安全的集合类,其特点是实现指定时间的阻塞读写,并且容量有界的。

1) 构造函数

public ArrayBlockingQueue(int
capacity, boolean fair) {

if (capacity <= 0)

throw new IllegalArgumentException();

this.items = (E[]) new Object[capacity];

lock = new ReentrantLock(fair);

notEmpty
= lock.newCondition();

notFull =  lock.newCondition();

}

初始化锁和两个锁上的Condition,一个为notEmpty,一个为notFull。

2. offer添加

public boolean offer(E
e, long timeout, TimeUnit unit)

throws InterruptedException {

if (e == null) throw new NullPointerException();

long nanos = unit.toNanos(timeout);

final
ReentrantLock lock = this.lock;

lock.lockInterruptibly();

try {

for (;;) {

if (count != items.length) {

insert(e);

return true;

}

if (nanos <= 0)

return false;

try {

nanos
= notFull.awaitNanos(nanos);

} catch (InterruptedException ie) {

notFull.signal(); // propagate to non-interrupted thread

throw ie;

}

}

} finally {

lock.unlock();---一定要释放

}

}

这个方法将元素插入数组的末尾,如果数组满,则进入等待,只到以下三种情况发生才继续:

被唤醒、达到指定的时间、当前线程被中断。

该方法首先将等待时间转换成纳秒。然后加锁,如果数组未满,则在末尾插入数据,如果数组已满,则调用notFull.awaitNanos进行等待。如果被唤醒或超时,重新判断是否满。如果线程被interrupt,则直接抛出异常。同时还可以选择put方法,此方法在数组已满的情况下会一直等待,知道数组不为空或线程被interrupt.

public void put(E
e) throws InterruptedException {

if (e == null) throw new NullPointerException();

final E[] items = this.items;

final
ReentrantLock lock = this.lock;

lock.lockInterruptibly();

try {

try {

while
(count == items.length)--本质是使用wait/notify机制就可以避免这些无谓的轮询,节省CPU的消耗

notFull.await();

} catch (InterruptedException ie) {

notFull.signal(); // propagate to non-interrupted thread

throw ie;

}

insert(e);

} finally {

lock.unlock();

}

}

接下来介绍重点的一对方法

public E
poll() {

final ReentrantLock lock = this.lock;

lock.lock();

try {

return (count == 0) ? null : extract();----空直接返回null,那么我们如何判定集合中的数据状况呢?我们就采用重入锁内部通过Sync轮询机制。这样是非常耗费CPU的.

} finally {

lock.unlock();

}

}

}

} finally {

lock.unlock();

}

}

public E
take() throws InterruptedException {

final ReentrantLock lock = this.lock;

lock.lockInterruptibly();

try {

while
(count == 0)

notEmpty.await();---为空阻塞.本质是使用wait/notify机制就可以避免这些无谓的轮询,节省CPU的消耗

return extract();

} finally {

lock.unlock();

}

}

ArrayBlockingQueue take()和poll()的一点区别

使用take()函数,如果队列中没有数据,则线程wait释放CPU,而poll()则不会等待,直接返回null;同样,空间耗尽时offer()函数不会等待,直接返回false,而put()则会wait,因此如果你使用while(true)来获得队列元素,千万别用poll(),CPU会100%的.

ArrayBlockingQueue take()和poll()等方法的小区别

时间: 2024-11-05 06:05:55

ArrayBlockingQueue take()和poll()等方法的小区别的相关文章

&nbsp; 中国菜刀使用方法以及小技巧

相信大多数的站长都用FTP来管理web空间,但是相对于菜刀来说FTP简直弱到爆.就数据库管理方面来说,phpmyadmin和帝国软件只能管理mysql数据库,而且在软件的体积上跟菜刀完全没法比,如果精通SQL语法,何必还要PHPMYADMIN呢?而且中国菜刀以其特色图形界面,支持MYSQL,MSSQL,ORACLE,INFOMIX,ACCESS,支持ADO方式连接的数据库. 服务端: 在服务端运行的代码如下: PHP: ASP: <%eval request("pass")%&g

国嵌内核驱动进阶班-7-4(Poll设备方法)

Poll 与系统select调用相对应 int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) Poll设备方法完成流程: 1. 使用poll_wait将等待队列添加到poll_table中 2. 返回描述设备的可读可写的设备掩码. ※ 掩码有: POLLIN 设备可读 POLLRDNORM 数据可读 POLLOUT 设备可写 POLLWRNORM 数据

关于 JS 面向对象继承属性和方法的小例子

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <h1>关于 JS 面向对象继承属性和方法的小例子</h1> </body> </html> <script> //人的构造函

Java方法继承、方法重载、方法覆盖小总结

转自:http://blog.csdn.net/cdsnmdl/article/details/3968688 ———————————————————————————————————— 1.方法继承:利用extends关键字一个方法继承另一个方法,而且只能直接继承一个类. 当Sub类和Base类在同一个包时Sub类继承Base类中的public/protected/默认级别的变量个方法 在不同包时继承public/protected级别的变量和方法. 2.方法重载:如果有两个方法的方法名相同,但

仿javascript中confirm()方法的小插件

10天没有写博客了,不知道为什么,心里感觉挺不舒服的,可能这是自己给自己规定要去完成的事情,没有按照计划执行,总会心里不怎么舒服.最近事情挺多的,终于今天抽空来更新一下博客了. 今天写的是一个小插件.平时我们习惯于使用javascript中自带的confirm()函数做出一个弹窗的效果,但是问题在于这样的弹窗非常不美观,大大降低了网页的整体效果. 好吧废话不多说,首先先来了解一下confirm()函数,下面应该注释得很清楚了. if(confirm("我们去阿里转山吧,好吗?")){/

Java易混小知识——equals方法和==的区别

一.equals方法和==的区别 1.equals是String对象的方法,可以通过".“调用. 2.== 是一个运算符. 二.常用的比较用法 1.基本数据类型比较. equals和==都比较两个数值 是否相等.相等即为true,不相等则为false. 2.引用对象的比较. equals和==都比较栈内存中的地址是否相等.相等即为true,不相等则为false. 三.易错点 1.String是一个特殊的引用类型.对于两个字符串的比较,不管是==还是equals这两者比较的都是字符串是否相同. 2

select、poll、epoll之间的区别

select.poll.epoll之间的区别总结[整理] select,poll,epoll都是IO多路复用的机制.I/O多路复用就通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作.但select,poll,epoll本质上都是同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的,而异步I/O则无需自己负责进行读写,异步I/O的实现会负责把数据从内核拷贝到用户空间.关于这三种IO多路复用的用法,前面

转:select、poll、epoll之间的区别总结[整理]

转:select.poll.epoll之间的区别总结[整理] select,poll,epoll都是IO多路复用的机制.I/O多路复用就通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作.但select,poll,epoll本质上都是同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的,而异步I/O则无需自己负责进行读写,异步I/O的实现会负责把数据从内核拷贝到用户空间.关于这三种IO多路复用的用法,

.net: 不能忽视的break——寻找VS2010和VS2012编译器的一个小区别

文中的问题来自于实际开发,但是实际开发中的代码逻辑比较复杂,因此下面的代码去掉了所有逻辑,只保留能体现问题的代码,类和都只为了说明问题,并不具有实际意义.下面首先看看下面的代码和现象. 1. 问题再现 下面的代码重现了场景, 看完这段代码是不有任何问题吗?下面看看输出结果. 1 public class IL 2 { 3 public List<InstanceOne> _instances = new List<InstanceOne>(); 4 public InstanceO