欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

BlockingQueue阻塞队列详解

程序员文章站 2023-08-26 15:16:04
BlockingQueue 和 SynchronousQueueBlockingQueueBlockingQueue的四组API:① add 和 removeadd(E e) :将指定的元素插入到此队列中,成功则返回true,队列满了插入失败则抛出异常java.lang.IllegalStateException: Queue fullremove() :返回并删除队首元素,如果队列为空删除失败则抛出异常java.util.NoSuchElementExceptionelement() :返...

BlockingQueue 和 SynchronousQueue

BlockingQueue

BlockingQueue阻塞队列详解
BlockingQueue阻塞队列详解
BlockingQueue的四组API:
① add 和 remove
add(E e) :将指定的元素插入到此队列中,成功则返回true,队列满了插入失败则抛出异常java.lang.IllegalStateException: Queue full
remove() :返回并删除队首元素,如果队列为空删除失败则抛出异常java.util.NoSuchElementException
element() :返回队首元素,队列为空则抛出异常java.util.NoSuchElementException

② offer 和 poll
offer(E e) :将指定的元素插入到此队列中,成功则返回true,队列满了插入失败则返回false
poll() :返回并删除队首元素,如果队列为空删除失败则返回null
peek() :返回队首元素,队列为空则返回null

③ put 和 take
put(E e) :将指定的元素插入到此队列中,没有返回值,如果队列满了则一直等待(阻塞),直到有元素从队列中被取出
take() :返回并删除队首元素,如果队列为空则一直等待(阻塞),直到有新的元素插入队列

④ offer(E e, long timeout, TimeUnit unit) 和 poll(long timeout, TimeUnit unit)
offer(E e, long timeout, TimeUnit unit) :将指定元素插入队列中,如果队列已满则等待给定时间,如果还是无法插入则返回false并执行下一条语句
poll(long timeout, TimeUnit unit) :返回并删除队首元素,如果队列为空则等待给定时间,如果队列还是为空无元素删除则返回null并执行下一条语句

public class BlockingQueueTest {
    public static void main(String[] args) throws InterruptedException {
        test4();
    }

    public static void test1(){
        // 创建阻塞队列并设置容量大小
        ArrayBlockingQueue<String> arrayBlockingQueue = new ArrayBlockingQueue<>(3);

        System.out.println(arrayBlockingQueue.add("a")); // 将元素插入队列,插入成功返回true
        System.out.println(arrayBlockingQueue.add("b"));
        System.out.println(arrayBlockingQueue.add("c"));
        //System.out.println(arrayBlockingQueue.add("d")); // 插入失败,超出队列容量抛出异常:java.lang.IllegalStateException: Queue full

        System.out.println(arrayBlockingQueue.element()); // 返回队首元素,队列为空则抛出异常:java.util.NoSuchElementException

        System.out.println(arrayBlockingQueue.remove()); // 返回并删除队首元素
        System.out.println(arrayBlockingQueue.remove());
        System.out.println(arrayBlockingQueue.remove());
        //System.out.println(arrayBlockingQueue.remove()); // 删除失败,队列为空则抛出异常:java.util.NoSuchElementException
    }

    public static void test2(){
        // 创建阻塞队列并设置容量大小
        ArrayBlockingQueue<String> arrayBlockingQueue = new ArrayBlockingQueue<>(3);

        System.out.println(arrayBlockingQueue.offer("a")); // 将元素插入队列,插入成功返回true
        System.out.println(arrayBlockingQueue.offer("b"));
        System.out.println(arrayBlockingQueue.offer("c"));
        System.out.println(arrayBlockingQueue.offer("d")); // 插入失败,超出队列容量返回false

        System.out.println(arrayBlockingQueue.peek()); // 返回队首元素,队列为空则返回null

        System.out.println(arrayBlockingQueue.poll()); // 返回并删除队首元素
        System.out.println(arrayBlockingQueue.poll());
        System.out.println(arrayBlockingQueue.poll());
        System.out.println(arrayBlockingQueue.poll()); // 删除失败,队列为空返回null
    }

    public static void test3() throws InterruptedException {
        // 创建阻塞队列并设置容量大小
        ArrayBlockingQueue<String> arrayBlockingQueue = new ArrayBlockingQueue<>(3);

        arrayBlockingQueue.put("a"); // 将指定的元素插入到此队列中,没有返回值
        arrayBlockingQueue.put("b");
        arrayBlockingQueue.put("c");
        //arrayBlockingQueue.put("d"); // 队列满了则一直等待直到有元素从队列中取出

        System.out.println(arrayBlockingQueue.take()); // 返回并删除队首元素
        System.out.println(arrayBlockingQueue.take());
        System.out.println(arrayBlockingQueue.take());
        //System.out.println(arrayBlockingQueue.take()); // 如果队列为空则一直等待(阻塞),直到有新的元素插入队列
    }

    public static void test4() throws InterruptedException {
        // 创建阻塞队列并设置容量大小
        ArrayBlockingQueue<String> arrayBlockingQueue = new ArrayBlockingQueue<>(3);

        arrayBlockingQueue.offer("a");
        arrayBlockingQueue.offer("b");
        arrayBlockingQueue.offer("c");
        System.out.println(arrayBlockingQueue.offer("d", 2, TimeUnit.SECONDS)); // 当队列满了,等待2秒还是插入不了则返回false并执行下一条语句

        System.out.println(arrayBlockingQueue.poll());
        System.out.println(arrayBlockingQueue.poll());
        System.out.println(arrayBlockingQueue.poll());
        System.out.println(arrayBlockingQueue.poll(2,TimeUnit.SECONDS)); // 当队列为空,等待2秒还是为空无元素删除则返回null并执行下一条语句
    }
}

SynchronousQueue

SynchronousQueue同步队列是BlockingQueue的实现类
同步队列没有任何内部容量,甚至没有一个容量
SynchronousQueue同步队列其中每个插入操作必须等待另一个线程相应的删除操作,反之亦然
即插入一个元素必须等待删除取出一个元素后才能再插入一个元素,取出一个元素必须等待插入一个元素后才能取出
可以把SynchronousQueue同步队列想象成容量为1的一个阻塞队列BlockingQueue
public class SynchronousQueueTest {
    public static void main(String[] args) {
        SynchronousQueue<String> synchronousQueue = new SynchronousQueue<>();
        new Thread(()->{
            try {
                System.out.println(Thread.currentThread().getName()+"插入元素 a");
                synchronousQueue.put("a");
                System.out.println(Thread.currentThread().getName()+"插入元素 b");
                synchronousQueue.put("b");
                System.out.println(Thread.currentThread().getName()+"插入元素 c");
                synchronousQueue.put("c");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"A").start();
        new Thread(()->{
            try{
                TimeUnit.SECONDS.sleep(2);
                System.out.println(Thread.currentThread().getName()+"取出元素"+synchronousQueue.poll());
                TimeUnit.SECONDS.sleep(2);
                System.out.println(Thread.currentThread().getName()+"取出元素"+synchronousQueue.poll());
                TimeUnit.SECONDS.sleep(2);
                System.out.println(Thread.currentThread().getName()+"取出元素"+synchronousQueue.poll());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"B").start();
    }
}

结果:

A插入元素 a
B取出元素a
A插入元素 b
B取出元素b
A插入元素 c
B取出元素c
由于队列没有容量,因此不能调用peek操作,因为只有移除元素时才有元素

本文地址:https://blog.csdn.net/weixin_43912697/article/details/114328321