标题:
Java 容器源码分析之ArrayBlockingQueue和LinkedBlockingQueue(4)
[打印本页]
作者:
look_w
时间:
2019-1-11 18:35
标题:
Java 容器源码分析之ArrayBlockingQueue和LinkedBlockingQueue(4)
数据的删除LinkedBlockingQueue有不同的几个数据删除方法,poll、take、remove方法。
poll方法:
[url=]
[/url]
public
E poll() {
final
AtomicInteger count =
this
.count;
if
(count.get() == 0)
//
如果元素个数为0
return
null
;
//
返回null
E x =
null
;
int
c = -1
;
final
ReentrantLock takeLock =
this
.takeLock; takeLock.lock();
//
拿锁加锁,保证调用poll方法的时候只有1个线程
try
{
if
(count.get() > 0) {
//
判断队列里是否还有数据
x = dequeue();
//
删除头结点
c = count.getAndDecrement();
//
元素个数-1
if
(c > 1)
//
如果队列里还有元素
notEmpty.signal();
//
在拿锁的条件对象notEmpty上唤醒正在等待的线程,表示队列里还有数据,可以再次消费
} }
finally
{ takeLock.unlock();
//
释放拿锁,让其他线程可以调用poll方法
}
if
(c == capacity)
//
由于存在放锁和拿锁,这里可能放锁一直在添加数据,count会变化。这里的if条件表示如果队列中还可以再插入数据
signalNotFull();
//
在放锁的条件对象notFull上唤醒正在等待的1个线程,表示队列里还能再次添加数据
return
x;}
[url=]
[/url]
take方法:[url=]
[/url]
public
E take()
throws
InterruptedException { E x;
int
c = -1
;
final
AtomicInteger count =
this
.count;
final
ReentrantLock takeLock =
this
.takeLock; takeLock.lockInterruptibly();
//
拿锁加锁,保证调用take方法的时候只有1个线程
try
{
while
(count.get() == 0) {
//
如果队列里已经没有元素了
notEmpty.await();
//
阻塞并挂起当前线程
} x
= dequeue();
//
删除头结点
c = count.getAndDecrement();
//
元素个数-1
if
(c > 1)
//
如果队列里还有元素
notEmpty.signal();
//
在拿锁的条件对象notEmpty上唤醒正在等待的线程,表示队列里还有数据,可以再次消费
}
finally
{ takeLock.unlock();
//
释放拿锁,让其他线程可以调用take方法
}
if
(c == capacity)
//
由于存在放锁和拿锁,这里可能放锁一直在添加数据,count会变化。这里的if条件表示如果队列中还可以再插入数据
signalNotFull();
//
在放锁的条件对象notFull上唤醒正在等待的1个线程,表示队列里还能再次添加数据
return
x;}
[url=]
[/url]
remove方法:
[url=]
[/url]
public
boolean
remove(Object o) {
if
(o ==
null
)
return
false
; fullyLock();
//
remove操作要移动的位置不固定,2个锁都需要加锁
try
{
for
(Node<E> trail = head, p = trail.next;
//
从链表头结点开始遍历
p !=
null
; trail
= p, p =
p.next) {
if
(o.equals(p.item)) {
//
判断是否找到对象
unlink(p, trail);
//
修改节点的链接信息,同时调用notFull的signal方法
return
true
; } }
return
false
; }
finally
{ fullyUnlock();
//
2个锁解锁
}}
[url=]
[/url]
LinkedBlockingQueue的take方法对于没数据的情况下会阻塞,poll方法删除链表头结点,remove方法删除指定的对象。
需要注意的是remove方法由于要删除的数据的位置不确定,需要2个锁同时加锁。
欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/)
Powered by Discuz! 7.0.0