ConcurrentLinkedQueue是非阻塞线程安全(volatile不能完全保证线程安全)的队列,适用于“高并发”的场景。是一个基于链表节点的无界线程安全队列,按照 FIFO(先进先出,尾先进头先出)原则对元素进行排序。队列元素中不可以放置null元素(内部实现的特殊节点除外)。
volatile作用:
- volatile的作用是保证共享变量的可见性,不能保证原子性,也不能保证线程安全。
- volatile的作用是确保所有线程在同一时刻读取到的共享变量的值是一样的。
- 如果某个线程对volatile修饰的共享变量进行更新,那么其他线程可以立刻看到这个更新。
ConcurrentLinkedQueue的数据结构,如下图所示:
特点:
- 都继承于
AbstractQueue
并实现BlockingQueue
,说明有Queue的一些特性例如FIFO和一些方法。 - ConcurrentLinkedQueue内部是通过链表来实现的。同时包含链表的头节点head和尾节点tail。ConcurrentLinkedQueue按照 FIFO(先进先出)原则对元素进行存储。元素都是从尾部插入到链表,从头部开始返回。
- ConcurrentLinkedQueue的链表Node中的next的类型是
volatile
,而且链表数据item的类型也是volatile
。ConcurrentLinkedQueue就是通过volatile
来实现多线程之间内存数据的可见性,详看本人博客volatile(一)和volatile(二)。 - 其中head节点存放链表第一个item为null的节点,tail则并不是总指向最后一个节点。
实操代码:
//ConcurrentLinkedQueue ------start FIFO(尾先进头先出)ConcurrentLinkedQueue<Integer>concurrentLinkedQueue = new ConcurrentLinkedQueue();//将元素添加到队尾 add()内部也是调用的offer()concurrentLinkedQueue.add(331);//将元素添加到队尾concurrentLinkedQueue.offer(2);concurrentLinkedQueue.add(4);concurrentLinkedQueue.add(1);Arrays.stream(concurrentLinkedQueue.toArray()).forEach(a->{System.out.println("ConcurrentLinkedQueue add offer "+a);});/*** ConcurrentLinkedQueue add offer 331* ConcurrentLinkedQueue add offer 2* ConcurrentLinkedQueue add offer 4* ConcurrentLinkedQueue add offer 1*/Integer peek2 = concurrentLinkedQueue.peek();System.out.println("ConcurrentLinkedQueue peek "+peek2);//ConcurrentLinkedQueue peek 331//内部也是调的peek()方法
Integer peek3 = concurrentLinkedQueue.element();System.out.println(