1 ConcurrentLinkedQueue
HOPS延迟更新策略:
tail:当前tail节点的下一个节点为null时,只插入节点但是不更新tail;当前tail节点的下一个节点不为null时,才会定位真正的tail。
head:当前head的item不为null时只删除节点不更新head;当前head的item为null的时候才定位新的head。
HOPS策略减少了CAS更新,采用无锁的方式,可以达到更高的并发。
2 BlockingQueue和BlockingDeque
2.1 简介
BlockingQueue 阻塞队列,通常使用场景时是一个线程调用take方法获取队列头结点,一个线程调用put方法添加尾结点。该队列是有限的,当阻塞队列达到了上限,那么负责插入对象的线程就会发生阻塞。
对于队列达到上限不同方法有不同的处理方式:
抛异常:操作无法执行那么抛出异常。
特定值:操作无法执行则返回特定的值比如false。
阻塞:操作无法执行,那么当前线程被阻塞直到能够执行。
超时:操作无法立即执行,那么当前线程被阻塞直到能够执行,但是等待时间不会超过给定的值,如果超过就返回特定值。
BlockingDeque实现了BlockingQueue接口,该接口的实例时双向的,即两边都可以添加或删除。
2.2BlockingQueue的实现类
2.2.1 DelayQueue
DelayQueue实现了BlockQueue,延迟队列。其特征是入队之后的元素会按照一定顺序排序,并且每次头结点出队都会有延迟。
DelayQueue队列中每个对象都必须实现Delayed接口,getDelay方法的返回值是该对象剩余的延迟时间,当返回值<=0的时候说明已经过了延迟期可以出队了。
DelayQueue使用PriorityQueue类,PriorityQueue是一个优先队列,根据用户的comparTo方法对对象按照优先级进行排序。
代码示例:
public class DelayQueueExample {
public static void main(String[] args) throws InterruptedException {
DelayQueue<DelayObject> queue = new DelayQueue<DelayObject>();
DelayObject object = new DelayObject("1",1);
DelayObject object2 = new DelayObject("2",2);
queue.put(object);
queue.put(object2);
DelayObject object3 = queue.take();
}
}
public class DelayObject implements Delayed {
private String name;
private long time;
private long startTime ;
public DelayObject(String name,long time) {
this.name = name;
this.time = time;
this.startTime = System.currentTimeMillis();
}
@Override
public long getDelay(TimeUnit unit) {//DelayQueue的take方法源码中unit输入为TimeUnit.NANOSECONDS
//这里的方法由程序员自己实现,我这里的逻辑是开始时间+延迟时间-当前时间,结果就是还需要延迟多久
return unit.convert(this.startTime+time-System.currentTimeMillis(),TimeUnit.MILLISECONDS);
}
//实现compareTo方法是为了给队列中的对象排序
@Override
public int compareTo(Delayed o) {
DelayObject ob = (DelayObject) o;
//延迟时间越长优先级越低
if(ob.time > this.time)
return -1;
else if(ob.time == this.time)
return 0;
return 1;
}
}
2.2.2 ArrayBlockingQueue
ArrayBlockingQueue是有界的阻塞队列,依赖于数组实现,所以一旦初始化的时候设置了上限,就无法再改变。
测试示例:
public class BlockingQueueArrayExample {
public static void main(String[] args) throws InterruptedException {
BlockingQueue queue = new ArrayBlockingQueue(10);
for(int i = 0;i<=10;i++){
// queue.add(i); //超出范围会报错
System.out.println(queue.offer(i));//超出返回会返回false
// queue.put(i); //超出返回当前线程会被阻塞
}
Object ob = queue.take();
}
}
2.2.3 LinkedBlockingQueue
LinkedBlockingQueue和ArrayBlockingQueue类似,不同的是LinkedBlockingQueue以链表的形式实现。
2.2.4 PriorityBockingQueue
PriorityBlockingQueue是有优先级的队列不能插入null。
2.2.5 LinkedTransferQueue
参考:JUC源码分析25-队列-LinkedTransferQueue_熊猫小牛牛的博客-CSDN博客_linkedtransferqueue
并发编程—— LinkedTransferQueue - 莫那-鲁道 - 博客园 (cnblogs.com)
2.3 BlockingDeque实现类
LinkedBlockingDeque是BlockingDeque的唯一实现类,这是一个双向队列可以从两端插入或者取出数据,当队列为空的时候,那么消费者线程会阻塞。