本文主要是介绍ConcurrentLinkedQueue浅析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
ConcurrentLinkedQueue是线程安全的无界非阻塞队列,其底层数据结构是使用单向链表实现,入队和出队操作是使用我们经常提到的CAS来保证线程安全的。
public class ConcurrentLinkedQueue<E> extends AbstractQueue<E>
implements Queue<E>, java.io.Serializable {
private static final long serialVersionUID = 196745693267521676L;
private transient volatile Node<E> head;// volatile 修饰的头节点
private transient volatile Node<E> tail;// volatile 修饰的尾节点
//匿名内部类
private static class Node<E> {
volatile E item;// volatile本节点的存储
volatile Node<E> next;// 下一个节点的引用
}
// 从队列的头部获取并移除,如果为空则返回null
public E poll() {
restartFromHead:
for (;;) {
for (Node<E> h = head, p = h, q;;) {
E item = p.item;
if (item != null && p.casItem(item, null)) {
// p.casItem(item, null) 通过cas操作移除头部元素
if (p != h)
updateHead(h, ((q = p.next) != null) ? q : p);
return item;
}
else if ((q = p.next) == null) {
updateHead(h, p);
return null;
}
else if (p == q)
continue restartFromHead;
else
p = q;
}
}
}
// 获取头部元素,没有就返回null,不会移除元素 同poll() 方法基本类似
// 少了一步 p.casItem(item, null)
public E peek() {
restartFromHead:
for (;;) {
for (Node<E> h = head, p = h, q;;) {
E item = p.item;
if (item != null || (q = p.next) == null) {
updateHead(h, p);
return item;
}
else if (p == q)
continue restartFromHead;
else
p = q;
}
}
}
// 移除某一个元素 队列中含有该元素就移除返回true,不含该元素就返回false
public boolean remove(Object o) {
if (o == null) return false;
Node<E> pred = null;
for (Node<E> p = first(); p != null; p = succ(p)) {
E item = p.item;
if (item != null &&
o.equals(item) &&
p.casItem(item, null)) { // cas操作移除元素
Node<E> next = succ(p);
if (pred != null && next != null)
pred.casNext(p, next);
return true;
}
pred = p;
}
return false;
}
//这个方法在多线程并发的情况下作用不大 没有锁机制 size得到的结果不确定
public int size() {
int count = 0;
for (Node<E> p = first(); p != null; p = succ(p))
if (p.item != null)
// Collection.size() spec says to max out
if (++count == Integer.MAX_VALUE)
break;
return count;
}
欢迎大家关注我的微信公众号 您的关注就是我不懈的动力
这篇关于ConcurrentLinkedQueue浅析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!