线程阻塞队列

96 阅读1分钟

这是我参与11月更文挑战的第28天,活动详情查看:2021最后一次更文挑战

阻塞队列

队列先进先出FIFO

存入时,如果队列满了,阻塞等待空出。

取出时,如果队列为空,阻塞等待生产。

image.png

Collection接口 -> queue接口 -> BlockingQueue接口 queue 下还有一个相反的接口AbstractQueue(非阻塞队列)

源码add时会判断插入的元素是否为空,然后lock加锁判断

public boolean offer(E e) {
        checkNotNull(e);
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            if (count == items.length)
                return false;
            else {
                enqueue(e);
                return true;
            }
        } finally {
            lock.unlock();
        }
    }

remove:可以指定想要抛出的值,如果有就溢出,没有找到就不移除。

public boolean remove(Object o) {
        if (o == null) return false;
        final Object[] items = this.items;
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            if (count > 0) {
                final int putIndex = this.putIndex;
                int i = takeIndex;
                do {
                    if (o.equals(items[i])) {
                        removeAt(i);
                        return true;
                    }
                    if (++i == items.length)
                        i = 0;
                } while (i != putIndex);
            }
            return false;
        } finally {
            lock.unlock();
        }
    }

抛出异常

// 设置队列的长度为3
        ArrayBlockingQueue< Object > objects = new ArrayBlockingQueue<>(3);
​
        boolean add1 = objects.add("1");
        boolean add2 = objects.add(1);
        boolean add3 = objects.add(new BlockQueue());
        boolean add4 = objects.add(1);
        System.out.println(add1);
        System.out.println(add2);
        System.out.println(add3);
  • add :插入
  • remove : 移除
  • element:获取队首元素

queue full:前三个为true,当插入第四个时add() ,超出队列的长度,就会抛出异常

NoSuchElementException:1.当列队为空,还执行remove时,会抛出异常 2.队列为空,执行获取队首操作element()

不抛出异常

  • offer : 插入
  • poll : 移除
  • pick:获取队首元素
    boolean add1 = objects.offer("1");
        boolean add2 = objects.offer(2);
        boolean add3 = objects.offer(3);
        // 当队列已满,不会插入,返回false
        boolean add4 = objects.offer(4);
​
        objects.poll();
        objects.poll();
        Object poll1 = objects.poll();
        // 当队列已空,不会再移除,返回null
        Object poll = objects.poll();

阻塞

  • put:插入 ,如果队列已满,会一直等待直到队列不慢
  • take: 移除,如果队列已空,会一直等待直到队列中有新的元素

阻塞超时

  • offer : 插入,并指定阻塞时间。当队列已满时,会等待timeout的时间,如果这段时间内还是满的,就会插入失败,返回false
  • poll : 移除,并指定阻塞时间。当队列为空时,会等待timeout时间。如果该段时间内还是空的,就移除失败,返回false
ArrayBlockingQueue< Object > objects = new ArrayBlockingQueue<>(3);
        boolean offer = objects.offer(1, 2, TimeUnit.SECONDS);
        System.out.println(offer);
        boolean offer2 = objects.offer(2, 2, TimeUnit.SECONDS);
        System.out.println(offer2);
        boolean offer3 = objects.offer(3, 10, TimeUnit.SECONDS);
        System.out.println(offer3);
​
        // 当队列已满时,会等待timeout的时间,如果这段时间内还是满的,就会插入失败,返回false
        boolean offer4 = objects.offer(3, 2, TimeUnit.SECONDS);
        System.out.println(offer4);
​
        Object poll = objects.poll(2, TimeUnit.SECONDS);
        System.out.println(poll);
        Object poll1 = objects.poll(2, TimeUnit.SECONDS);
        System.out.println(poll1);
        Object poll2 = objects.poll(2, TimeUnit.SECONDS);
        System.out.println(poll2);
        // 当队列为空时,会等待timeout时间。如果该段时间内还是空的,就移除失败,返回false
        Object poll3 = objects.poll(2, TimeUnit.SECONDS);
        System.out.println(poll3);