LinkedBlockingQueue

LinkedBlockingQueue是一个基于链表实现的阻塞队列,默认情况下,该阻塞队列的大小为Integer.MAX_VALUE,由于这个数值特别大,所以 LinkedBlockingQueue 也被称作无界队列

Posted by shrmars on March 23, 2024

一、 LinkedBlockingQueue介绍

        LinkedBlockingQueue是一个基于链表实现的阻塞队列,默认情况下,该阻塞队列的大小为Integer.MAX_VALUE,由于这个数值特别大,所以 LinkedBlockingQueue 也被称作无界队列,代表它几乎没有界限,队列可以随着元素的添加而动态增长,但是如果没有剩余内存,则队列将抛出OOM错误。所以为了避免队列过大造成机器负载或者内存爆满的情况出现,我们在使用的时候建议手动传一个队列的大小。

        LinkedBlockingQueue内部由单链表实现,只能从head取元素,从tail添加元素。LinkedBlockingQueue采用两把锁的锁分离技术实现入队出队互不阻塞,添加元素和获取元素都有独立的锁,也就是说LinkedBlockingQueue是读写分离的,读写操作可以并行执行。

二、LinkedBlockingQueue使用

  • 申明

    1
    2
    3
    4
    
    //指定队列的大小创建有界队列
    BlockingQueue<Integer> boundedQueue = new LinkedBlockingQueue<>(100);
    //无界队列
    BlockingQueue<Integer> unboundedQueue = new LinkedBlockingQueue<>();
    
  • 消费

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    @Service
    @Slf4j
    public class QueueComsumer {
        public static BlockingQueue<String> boundedQueue = new LinkedBlockingQueue<>(1000);
        @SneakyThrows
        @Async
        public void comsumer() {
            while (true) {
                String str = boundedQueue.take();
                log.info("收到消息:{}", str);
            }
        }
    }
    
  • 生产

    1
    2
    3
    4
    5
    
    @GetMapping("/queue")
        @IgnoreAuthorize
        public void getResult(String s) {
            boundedQueue.offer(s);
        }
    

三、常用方法

LinkedBlockingQueue添加元素的方法有三个:add、put、offer。且都是向队列尾部添加元素。

  • add:方法在添加元素的时候,若超出了度列的长度会直接抛出异常。

  • offer:方法添加元素,如果队列已满,直接返回false。

  • put:方法添加元素,如果队列已满,会阻塞直到有空间可以放。

LinkedBlockingQueue移除元素的方法有三个:poll、remove、take。且都是从队列中取出头部元素并从队列中删除。

  • poll: 若队列为空,返回null。

  • take:若队列为空,发生阻塞,等待到有元素。

  • remove::若队列为空,抛出NoSuchElementException异常。

LinkedBlockingQueue可以在构造函数的参数中指定大小,若没有指定大小,则默认大小为Integer.MAX_VALUE。LinkedBlockingQueue的大小不可为null。