LinkedBlockingQueue原理
来源:互联网 发布:在淘宝上怎么分期付款 编辑:程序博客网 时间:2024/05/16 16:06
LinkedBlockingQueue继承至BlockingQueue,是一个阻塞队列。
其内部实现原理如下:
- 通过静态内部类Node来存储元素,Node中有两个成员变量,一个是保存当前添加节点元素, 另一个指向下一个元素结点。因此LinkedBlockingQueue是一个阻塞链表结构
static class Node<E> { E item; - /**
- * One of:
* - the real successor Node
* - this Node, meaning the successor is head.next
* - null, meaning there is no successor (this is the last node)
*/
Node<E> next;
Node(E x) { item = x; }
} - 通过双锁来控制添加和删除元素,并通过Condition进行线程间通讯
- /** Lock held by take, poll, etc */
private final ReentrantLock takeLock = new ReentrantLock();
/** Wait queue for waiting takes */
private final Condition notEmpty = takeLock.newCondition();
/** Lock held by put, offer, etc */
private final ReentrantLock putLock = new ReentrantLock();
/** Wait queue for waiting puts */
private final Condition notFull = putLock.newCondition(); - 看一下put方法
- public void put(E e) throws InterruptedException {
//不可添加null元素
if (e == null) throw new NullPointerException();
int c = -1;
final ReentrantLock putLock = this.putLock;
final AtomicInteger count = this.count;
putLock.lockInterruptibly();
try {
/**与此 Condition 相关的锁以原子方式释放,并且出于线程调度的目的,将禁用当前线程,且在发生以下四种情况之一 以前,当前线程将一直处于休眠状态:
*其他某个线程调用此 Condition 的 signal() 方法,并且碰巧将当前线程选为被唤醒的线程;或者
*其他某个线程调用此 Condition 的 signalAll() 方法;或者
*其他某个线程中断当前线程,且支持中断线程的挂起;或者
*发生“虚假唤醒” **/
//有可能出现假唤醒,因为 Condition 应该总是在一个循环中被等待,并测试正被等待的状态声明
while (count.get() == capacity) {
notFull.await();
}
//入队
enqueue(e);
//count是AtomicInteger类型,以原子方式增长
c = count.getAndIncrement();
//如果队列中已添加元素的数量小于capacity,通知其它等待线程
if (c + 1 < capacity)
notFull.signal();
} finally {
//在finally块中释放锁,保证锁一定释放掉
putLock.unlock();
}
//如果队列中一个元素时,通知在读取锁上阻塞的线程
if (c == 0)
signalNotEmpty();
}
//入队,last总是指向最后一个元素
private void enqueue(E x) {
// assert putLock.isHeldByCurrentThread();
last = last.next = new Node<E>(x);
}
private void signalNotEmpty() {
final ReentrantLock takeLock = this.takeLock;
takeLock.lock();
try {
notEmpty.signal();
} finally {
takeLock.unlock();
}
} - take方法解析
- public E take() throws InterruptedException {
E x;
int c = -1;
final AtomicInteger count = this.count;
final ReentrantLock takeLock = this.takeLock;
takeLock.lockInterruptibly();
try {
//若队列为空,此线程释放读取锁,且线程阻塞,与put方法类似
while (count.get() == 0) {
notEmpty.await();
}
x = dequeue();
c = count.getAndDecrement();
//如果队列中还有元素,唤醒下个此condition阻塞的线程
if (c > 1)
notEmpty.signal();
} finally {
takeLock.unlock();
}
//如查当前队列中元素数量与capacity相等,去唤醒在写锁上阻塞的线程
//个人感觉应该是当前队列中元素数量小于capacity时,再去唤醒写锁上阻塞的线程吧?
if (c == capacity)
signalNotFull();
return x;
}
private E dequeue() {
Node<E> h = head;
Node<E> first = h.next;
h.next = h; // help GC
head = first;
E x = first.item;
first.item = null;
return x;
} Head元素中的E始终为null,当移移除元素时,将当前head指向的结点移除,而返回的值是head->next结点中的E,也就是El1中的E,并且将El1中的E设置为空,且head指向它
- LinkedBlockingQueue原理
- LinkedBlockingQueue 实现原理分析
- 推荐:LinkedBlockingQueue 实现原理分析
- LinkedBlockingQueue
- LinkedBlockingQueue
- LinkedBlockingQueue
- LinkedBlockingQueue
- LinkedBlockingQueue
- LinkedBlockingQueue
- LinkedBlockingQueue
- LinkedBlockingQueue
- LinkedBlockingQueue
- LinkedBlockingQueue
- LinkedBlockingQueue
- LinkedBlockingQueue
- LinkedBlockingQueue
- LinkedBlockingQueue
- linkedblockingqueue
- REST
- jquery ui datepicker demo
- objc_getAssociatedObject, objc_setAssociatedObject
- Ubuntu 手动安装jdk6
- java实现将多个文件打包成zip
- LinkedBlockingQueue原理
- 难过的时候看一看 再坏能有多坏!
- [Oracle] Active或Current联机日志文件丢失如何恢复?
- Java 在jvm外申请内存
- [转帖] c实现拼音首字母筛选
- 水平滚动代码
- MySQL 最新商业版备份工具使用方法
- Objective-C 04
- 线性表--双链表实现方式 (JAVA)