Java集合–非阻塞队列(ConcurrentLinkedQueue基础)

1.0 非阻塞队列

在上篇中,我们讲到了绿灯队列,以及阻塞队列中的多少个落到实处类。

本篇,大家继承对队列举办研究。而前日的大旨,则是非阻塞队列!在非阻塞队列中,ConcurrentLinkedQueue是重要代表。

在此以前,大家询问了哪些是阻塞队列,在此大家再简单地记忆下!

怎么是阻塞队列?

堵塞,顾名思义:当大家的生产者向队列中生产数据时,若队列已满,那么生产线程会暂停下来,直到队列中有可以存放数据的地方,才会三番五遍工作;而当大家的买主向队列中获取数据时,若队列为空,则消费者线程会暂停下来,直到容器中有元素出现,才能开展获取操作。

那就是阻塞队列。

那么,非阻塞队列又是什么样含义呢?

怎么着是非阻塞队列?

与阻塞队列相反,非阻塞队列的执行并不会被堵塞,无论是消费者的出队,还是生产者的入队。

在尾部,非阻塞队列使用的是CAS(compare and set)来兑现线程执行的非阻塞。

非阻塞队列的操作

与阻塞队列相同,非阻塞队列中的常用方法,也是出队和入队。

入队格局:

add():底层调用offer();

offer():Queue接口继承下来的方法,实现队列的入队操作,不会阻碍线程的执行,插入成功返回true;

出队章程:

poll():移动头结点指针,返回头结点元素,并将头结点元素出队;队列为空,则返回null;

peek():移动头结点指针,返回头结点元素,并不会将头结点元素出队;队列为空,则返回null;

上面,大家实际说下ConcurrentLinkedQueue的原理,以及贯彻!

ConcurrentLinkedQueue

ConcurrentLinkedQueue是三个线程安全的行列,基于链表结构完毕,是2个无界队列,理论上的话队列的长短可以极其增加。

与此外队列相同,ConcurrentLinkedQueue也利用的是先进先出(FIFO)入队规则,对成分举办排序。当大家向队列中添美成分时,新插入的成分会插入到行列的尾巴;而当大家取得三个因素时,它会从队列的尾部中取出。

因为ConcurrentLinkedQueue是链表结构,所以当入队时,插入的要素依次向后延伸,形成链表;而出队时,则从链表的首先个因素先导得到,依次递增;

不亮堂,小编这么描绘能或不能让你对链表的入队、出队发出多少个大体的思路!

差不离利用

值得注意的是,在动用ConcurrentLinkedQueue时,借使提到到行列是不是为空的论断,切记不可使用size()==0的做法,因为在size()方法中,是经过遍历整个链表来促成的,在队列成分很多的时候,size()方法充足消耗质量和时间,只是单纯的判断队列为空使用isEmpty()即可!!!

public class ConcurrentLinkedQueueTest {

    public static int threadCount = 100000;

    public static ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<String>();

    static class Offer implements Runnable {
        public void run() {
            if(queue.size()==0){
                String ele = new Random().nextInt(Integer.MAX_VALUE)+"";
                queue.offer(ele);
                System.out.println("入队元素为"+ele);
            }
        }
    }

    static class Poll implements Runnable {
        public void run() {
            if(!queue.isEmpty()){
                String ele = queue.poll();
                System.out.println("出队元素为"+ele);
            }
        }
    }

    public static void main(String[] agrs) {
        ExecutorService executorService = Executors.newFixedThreadPool(4);
        for(int x=0;x<threadCount;x++){
            executorService.submit(new Offer());
            executorService.submit(new Poll());
        }
        executorService.shutdown();
    }
}

下卷中,大家详细来介绍ConcurrentLinkedQueue的最底层已毕。

引言:在我研商源码时,发现无论是idea,依然eclipse,在debug方式下,跟踪ConcurrentLinkedQueue源码时都会生出bug,具体景况就是debug控制哈博罗内类的内存地址和实际的内存地址不雷同,导致代码在debug执行时并不会遵守正规逻辑来推行。

详细描述,可参照如下内容:神奇的控制台

消除方案:将ConcurrentLinkedQueue源码拷出,本地新建三个类,使用run执行,在措施的左右增添和谐的出口语句,打印出实际的内存地址,便可一商讨竟。倘若你不想对源码进行改动,只想用debug情势,指出将拷贝源码中的ConcurrentLinkedQueue的继承和兑现清一色去掉,方式如下:Java,public
class
ConcurrentLinkedQueue<E>
,那样也足以保障debug方式的常规运行。

相关文章