LinkedBlockingDeque
代码中的好味道
/**
* Removes and returns first element, or null if empty.
*/
private E unlinkFirst() {
// assert lock.isHeldByCurrentThread();
Node<E> f = first;
if (f == null)
return null;
Node<E> n = f.next;
E item = f.item;
f.item = null;
f.next = f; // help GC
first = n;
if (n == null)
last = null;
else
n.prev = null;
--count;
notFull.signal();
return item;
}
从上段代码中可以看到,临时节点f在使用完之后将f.next = f,即将下一个节点的指针指向自己。这样就不会与队列中存在的节点保持引用,那么JVM进行root扫描时候会将Node f视为垃圾进行回收,否则会出现内存泄漏的风险。
知识点
- ReentrantLock的使用
- Condition的使用 实例:
public E takeFirst() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lock();
try {
E x;
while ( (x = unlinkFirst()) == null)
notEmpty.await();
return x;
} finally {
lock.unlock();
}
}
public void putFirst(E e) throws InterruptedException {
if (e == null) throw new NullPointerException();
Node<E> node = new Node<E>(e);
final ReentrantLock lock = this.lock;
lock.lock();
try {
while (!linkFirst(node))
notFull.await();
} finally {
lock.unlock();
}
}
因为这对方法中使用的是同一把锁的Condition,所以会让让阻塞在方法中的其他线程互相进行唤醒。