基于链表实现的自己的阻塞队列,不过我只实现了add()和take()方法,有问题请指正!谢谢。。。
package myblockingqueue;
import java.lang.reflect.Field;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import sun.misc.Unsafe;
/*
* 采用生产者-消费者模式,当队列中空时,消费者线程放入等待队列
*
* 思想是,队列要满足多生产者多消费者
*/
public class MyBlockingQueue<T> {
private static Unsafe unsafe ;
private static long headOffset;
private static long tailOffset;
private static Condition notEmpty=new ReentrantLock().newCondition();
static {
try {
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
unsafe = (Unsafe) f.get(null);
headOffset = unsafe.objectFieldOffset(MyBlockingQueue.class.getDeclaredField("head"));
tailOffset = unsafe.objectFieldOffset(MyBlockingQueue.class.getDeclaredField("tail"));
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
static class Node<T>{
T item;
Node<T> next;
Node<T> prev;
Node(T t){
item=t;
next=null;
}
}
//头节点
private volatile Node<T> head;
//尾节点
private volatile Node<T> tail;
//队列中的元素总数
private AtomicInteger count;
public int getCount() {
return count.get();
}
public MyBlockingQueue(){
tail=head=null;
count=new AtomicInteger(0);
}
//链表尾添加节点
public void add(T t) {
Node<T> newNode = new Node<T>(t);
for (;;) {
Node<T> pred = tail;
if (pred != null) {
newNode.prev=pred;
if (unsafe.compareAndSwapObject(this, tailOffset, pred, newNode)) {
//System.out.println(Thread.currentThread().getName()+" 调用了add()");
pred.next=newNode;
count.incrementAndGet();
return;
}
}
else {
if (unsafe.compareAndSwapObject(this, headOffset, null, newNode)) {
//System.out.println(Thread.currentThread().getName()+" 调用了add()");
tail=head;
count.incrementAndGet();
return;
}
}
}
}
public T take() {
for(;;) {
Node<T> hNode=head;
if(hNode!=null) {
//当头节点等于尾节点的时候直接返回
if(hNode==tail) {
if (unsafe.compareAndSwapObject(this, headOffset, hNode, null)) {
count.decrementAndGet();
tail=head;
return hNode.item;
}
}
//当队列为空时线程回做无限循环,此时假如有一个线程向队列里面添加了数据,并且还没有执行到tail=head;然后取数据的线程已经执行到这儿了
//即 head.next=null,后面hnNode.prev = null;就会报NullPointerException错,我的解决办法是用continue,以保证当队列中只有一个结点的时候,
//永远都是调用上面的if语句;
else {
if(head==null||head.next==null)
continue;
Node<T> hnNode = head.next;
hNode.next = null;
if (unsafe.compareAndSwapObject(this, headOffset, hNode, hnNode)) {
hnNode.prev = null;
count.decrementAndGet();
return hNode.item;
}
}
}
else {
//这个地方不好,因为当队列中没有节点是会一直for循环,导致线程空消耗
continue;
}
}
}
}