第一篇详细画出了在入队和出队时的操作,看的真的很费时,说实话,我看了好几遍才动手开始画队列变换的图,并且在画图时还时不时的修正了很多次。。。总结出,对于jdk源码的话,多看几遍总能看出作者的意图的,不要害怕看不懂,看不懂第一遍,看二遍,三遍。
这次的博客去看下此类中的其他一些方法,准备为将来的使用坐下基础。
succ方法,向后推进方法,可以看出获取的是当前节点的后继节点,比较了 p 和next是否相等,在第一篇博客分析时,发现在出队情况下,是有可能出现next指向自身的节点,出现这个节点,意味着出队执行成功,并且设置了新的head节点,head节点指向了下一个有效的队列头。
final Node<E> succ(Node<E> p) {
Node<E> next = p.next;
return (p == next) ? head : next;
}
1. item 不为null,更新head指向,并返回当前item值。
2.item为 null,判断当前节点是否到达了尾部,如果是尾部的话,更新head节点指于此,如果不是尾部的话,判断是够指向自身,都不是的话,p节点后移,重新获取下一个节点的item值。peek方法总的来说是获取head节点之后第一个有效节点。
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;
}
}
}
first方法。返回的是head节点之后的第一个不为null的有效节点的item值,可以看见,如果当前节点到达尾部的话,会更新一下head的值,并且会判断当前尾部节点的item是否是null,是的话返回空节点,不是的话返回有效节点
Node<E> first() {
restartFromHead:
for (;;) {
for (Node<E> h = head, p = h, q;;) {
boolean hasItem = (p.item != null);
if (hasItem || (q = p.next) == null) {
updateHead(h, p);
return hasItem ? p : null;
}
else if (p == q)
continue restartFromHead;
else
p = q;
}
}
}
isEmpty 字面意思判空。
如果head处的节点item值不为null,那么first会立即返回这个节点,立马知道这个队列不空。
如果first返回的是null的话,说明从head处读取到之后的节点都为null一直到最后的尾部节点,依然是null,才最终返回null。注意此处是从head节点开始读取的,head节点在出队操作中会不断变化。那么只有在这个队列全为null时,才会去遍历整个队列。
public boolean isEmpty() {
return first() == null;
}
可以看见size方法并不适用于判空处理,它会循环整个队列,计算出count值,消耗极大,并且这个count的值也不是准确的,多线程情况下有可能不靠谱,需要我们手动去做同步,注意一下。
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;
}
contains方法,去队列中寻找是否包含这个item项的节点。跟size方法一样,使用succ方式去遍历,但是这个方法一样会出现数据不同步的情况。
public boolean contains(Object o) {
if (o == null) return false;
for (Node<E> p = first(); p != null; p = succ(p)) {
E item = p.item;
if (item != null && o.equals(item))
return true;
}
return false;
}
使用ConcurrentLinkedQueue实现生产者消费者went
public class TestConcurrentLinkedDeque {
public static void main(String[] args) {
ConcurrentLinkedQueue<Food> foods = new ConcurrentLinkedQueue<Food>();
final Provider provider = new Provider(foods);
final Customer customer = new Customer(foods);
for(int i = 0; i < 10; i ++){
new Thread(new Runnable() {
public void run() {
provider.runP();
}
}).start();
}
for(int i = 0; i < 10; i ++){
new Thread(new Runnable() {
public void run() {
customer.runC();
}
}).start();
}
}
}
public class Provider {
private ConcurrentLinkedQueue<Food> foods;
/*采用原子Integer,可以完美解决多线程环境下数目的变换*/
private AtomicInteger num = new AtomicInteger();
public Provider(ConcurrentLinkedQueue<Food> foods) {
this.foods = foods;
}
public void runP() {
// TODO Auto-generated method stub
while (true) {
int index = num.incrementAndGet();
String name = "甜品 "+index+" 号";
try {
foods.offer(new Food(index, name));
System.out.println(Thread.currentThread()+"生产了第 "+ index + "号 食品: "+name + System.currentTimeMillis());
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public class Customer {
private ConcurrentLinkedQueue<Food> foods;
public Customer(ConcurrentLinkedQueue<Food> foods) {
this.foods = foods;
}
public void runC() {
// TODO Auto-generated method stub
while (true) {
try {
Food food = foods.poll();
if(food == null){
System.err.println(Thread.currentThread()+ "消费失败,无数据生产出 " +System.currentTimeMillis());
}else {
System.err.println(Thread.currentThread()+ "消费了第 "+food.getNum()+"食品 : " + food.getName()+System.currentTimeMillis());
Thread.sleep(2000);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Thread[Thread-0,5,main]生产了第 1号 食品: 甜品 1 号1496710329448
Thread[Thread-2,5,main]生产了第 2号 食品: 甜品 2 号1496710329448
Thread[Thread-4,5,main]生产了第 3号 食品: 甜品 3 号1496710329449
Thread[Thread-6,5,main]生产了第 4号 食品: 甜品 4 号1496710329449
Thread[Thread-8,5,main]生产了第 5号 食品: 甜品 5 号1496710329449
Thread[Thread-10,5,main]消费了第 1食品 : 甜品 1 号1496710329450
Thread[Thread-12,5,main]消费了第 2食品 : 甜品 2 号1496710329450
Thread[Thread-14,5,main]消费了第 3食品 : 甜品 3 号1496710329450
Thread[Thread-16,5,main]消费了第 4食品 : 甜品 4 号1496710329451
Thread[Thread-18,5,main]消费了第 5食品 : 甜品 5 号1496710329451
Thread[Thread-11,5,main]消费了第 6食品 : 甜品 6 号1496710329451
Thread[Thread-13,5,main]消费了第 7食品 : 甜品 7 号1496710329451
Thread[Thread-15,5,main]消费了第 8食品 : 甜品 8 号1496710329451
Thread[Thread-17,5,main]消费了第 9食品 : 甜品 9 号1496710329451
Thread[Thread-19,5,main]消费了第 10食品 : 甜品 10 号1496710329452
Thread[Thread-1,5,main]生产了第 6号 食品: 甜品 6 号1496710329451
Thread[Thread-3,5,main]生产了第 7号 食品: 甜品 7 号1496710329451
Thread[Thread-5,5,main]生产了第 8号 食品: 甜品 8 号1496710329451
Thread[Thread-7,5,main]生产了第 9号 食品: 甜品 9 号1496710329451
Thread[Thread-9,5,main]生产了第 10号 食品: 甜品 10 号1496710329451
Thread[Thread-10,5,main]消费了第 12食品 : 甜品 12 号1496710331450
Thread[Thread-14,5,main]消费了第 13食品 : 甜品 13 号1496710331450
Thread[Thread-12,5,main]消费了第 11食品 : 甜品 11 号1496710331450
Thread[Thread-18,5,main]消费了第 14食品 : 甜品 14 号1496710331451
Thread[Thread-16,5,main]消费了第 15食品 : 甜品 15 号1496710331451
Thread[Thread-11,5,main]消费了第 16食品 : 甜品 16 号1496710331451
Thread[Thread-13,5,main]消费了第 17食品 : 甜品 17 号1496710331451
Thread[Thread-15,5,main]消费了第 18食品 : 甜品 18 号1496710331451
Thread[Thread-0,5,main]生产了第 11号 食品: 甜品 11 号1496710331448
Thread[Thread-17,5,main]消费了第 19食品 : 甜品 19 号1496710331452
Thread[Thread-2,5,main]生产了第 12号 食品: 甜品 12 号1496710331448
Thread[Thread-19,5,main]消费了第 20食品 : 甜品 20 号1496710331452
Thread[Thread-4,5,main]生产了第 13号 食品: 甜品 13 号1496710331449
Thread[Thread-6,5,main]生产了第 14号 食品: 甜品 14 号1496710331449
Thread[Thread-8,5,main]生产了第 15号 食品: 甜品 15 号1496710331449
Thread[Thread-1,5,main]生产了第 16号 食品: 甜品 16 号1496710331451
Thread[Thread-3,5,main]生产了第 17号 食品: 甜品 17 号1496710331451
Thread[Thread-9,5,main]生产了第 18号 食品: 甜品 18 号1496710331451
Thread[Thread-5,5,main]生产了第 19号 食品: 甜品 19 号1496710331451
Thread[Thread-7,5,main]生产了第 20号 食品: 甜品 20 号1496710331451
Thread[Thread-10,5,main]消费了第 21食品 : 甜品 21 号1496710333450
Thread[Thread-12,5,main]消费了第 22食品 : 甜品 22 号1496710333450
Thread[Thread-14,5,main]消费了第 23食品 : 甜品 23 号1496710333450
Thread[Thread-16,5,main]消费了第 24食品 : 甜品 24 号1496710333451
Thread[Thread-18,5,main]消费了第 25食品 : 甜品 25 号1496710333451
Thread[Thread-11,5,main]消费了第 26食品 : 甜品 26 号1496710333451
Thread[Thread-15,5,main]消费失败,无数据生产出 1496710333451
Thread[Thread-15,5,main]消费失败,无数据生产出 1496710333451
Thread[Thread-15,5,main]消费失败,无数据生产出 1496710333451
Thread[Thread-15,5,main]消费了第 27食品 : 甜品 27 号1496710333451
Thread[Thread-13,5,main]消费了第 28食品 : 甜品 28 号1496710333451
Thread[Thread-0,5,main]生产了第 21号 食品: 甜品 21 号1496710333448
Thread[Thread-2,5,main]生产了第 22号 食品: 甜品 22 号1496710333448
Thread[Thread-4,5,main]生产了第 23号 食品: 甜品 23 号1496710333449
Thread[Thread-6,5,main]生产了第 24号 食品: 甜品 24 号1496710333449
Thread[Thread-8,5,main]生产了第 25号 食品: 甜品 25 号1496710333449
Thread[Thread-3,5,main]生产了第 26号 食品: 甜品 26 号1496710333451
Thread[Thread-1,5,main]生产了第 27号 食品: 甜品 27 号1496710333451
Thread[Thread-9,5,main]生产了第 28号 食品: 甜品 28 号1496710333451
Thread[Thread-5,5,main]生产了第 29号 食品: 甜品 29 号1496710333451
Thread[Thread-7,5,main]生产了第 30号 食品: 甜品 30 号1496710333451
Thread[Thread-17,5,main]消费了第 29食品 : 甜品 29 号1496710333452
Thread[Thread-19,5,main]消费了第 30食品 : 甜品 30 号1496710333452
Thread[Thread-0,5,main]生产了第 31号 食品: 甜品 31 号1496710335449
Thread[Thread-2,5,main]生产了第 32号 食品: 甜品 32 号1496710335449
Thread[Thread-4,5,main]生产了第 33号 食品: 甜品 33 号1496710335450
Thread[Thread-8,5,main]生产了第 34号 食品: 甜品 34 号1496710335450
Thread[Thread-6,5,main]生产了第 35号 食品: 甜品 35 号1496710335450
Thread[Thread-3,5,main]生产了第 36号 食品: 甜品 36 号1496710335452
Thread[Thread-1,5,main]生产了第 37号 食品: 甜品 37 号1496710335452
Thread[Thread-9,5,main]生产了第 38号 食品: 甜品 38 号1496710335452
Thread[Thread-5,5,main]生产了第 39号 食品: 甜品 39 号1496710335452
Thread[Thread-7,5,main]生产了第 40号 食品: 甜品 40 号1496710335452
Thread[Thread-10,5,main]消费了第 31食品 : 甜品 31 号1496710335451
Thread[Thread-12,5,main]消费了第 32食品 : 甜品 32 号1496710335451
Thread[Thread-14,5,main]消费了第 33食品 : 甜品 33 号1496710335451
Thread[Thread-16,5,main]消费了第 34食品 : 甜品 34 号1496710335452
Thread[Thread-18,5,main]消费了第 35食品 : 甜品 35 号1496710335452
Thread[Thread-11,5,main]消费了第 36食品 : 甜品 36 号1496710335452
Thread[Thread-13,5,main]消费了第 37食品 : 甜品 37 号1496710335452
Thread[Thread-15,5,main]消费失败,无数据生产出 1496710335452
Thread[Thread-15,5,main]消费了第 38食品 : 甜品 38 号1496710335452
Thread[Thread-17,5,main]消费了第 39食品 : 甜品 39 号1496710335453
Thread[Thread-19,5,main]消费了第 40食品 : 甜品 40 号1496710335453
实现方式和LinkBlobkedQueue类似