5.阻塞队列

发现队列Queue和List/Set平级!
阻塞队列的四组API:
方式
抛出异常
有返回值,不抛出异常
阻塞 等待
超时等待
添加
add
offer()
put()
offer
移除
remove
poll()
take()
poll
检测队首元素
element
peek()
   

1.抛出异常api检测:add/remove/element
    重点1:创建一个容量为3的队列
        ArrayBlockingQueue arrayBlockingQueue=new ArrayBlockingQueue<>(3);
        arrayBlockingQueue.add(1);
        arrayBlockingQueue.add(2);
        arrayBlockingQueue.add(3);
    重点2:往里放入多于容量的数据,此时会抛出异常:Exception in thread "main" java.lang.IllegalStateException: Queue full
        arrayBlockingQueue.add(4);
    重点3:移除元素-->输出1:发现队列的特点:先进先出
        System.out.println(arrayBlockingQueue.remove());
        移除指定的元素
        arrayBlockingQueue.remove(2)
        如果对队列中已经没有元素,再次调用arrayBlockingQueue.remove();
        会报错:Exception in thread "main" java.util.NoSuchElementException
    重点5:检测队首元素-->返回的是队首的元素!
        System.out.println(arrayBlockingQueue.element());

2.返回boolean值,不抛出异常!offer/poll/peek
        ArrayBlockingQueue arrayBlockingQueue=new ArrayBlockingQueue<>(3);
        System.out.println(arrayBlockingQueue.offer(1));
        System.out.println(arrayBlockingQueue.offer(2));
        System.out.println(arrayBlockingQueue.offer(3));
        重点1:使用offer标签添加元素,上述三条输出true,下面输出false,不会抛出异常!
        System.out.println(arrayBlockingQueue.offer(4));
    重点2:取出操作:
        System.out.println(arrayBlockingQueue.poll());
        System.out.println(arrayBlockingQueue.poll());
        System.out.println(arrayBlockingQueue.poll());
        System.out.println(arrayBlockingQueue.poll());
        输出:不抛异常,取完后返回null
            1
            2
            3
            null

3.阻塞等待:put/take
        ArrayBlockingQueue arrayBlockingQueue = new ArrayBlockingQueue<>(3);
        arrayBlockingQueue.put("1");
        arrayBlockingQueue.put("2");
        arrayBlockingQueue.put("3");
    重点1:控制台会输出-->3放入成功,队列已满..
        System.out.println("3放入成功,队列已满..");
    重点2:会在此处阻塞,后续打印不会进行..
        arrayBlockingQueue.put("4");
        System.out.println("检测4是否可以放置成功!");
        
4.超时等待/offer/poll传入参数
        ArrayBlockingQueue arrayBlockingQueue = new ArrayBlockingQueue<>(3);
        //重点1:传入参数(放入队列元素,超时时间,超时时间单位)
        System.out.println(arrayBlockingQueue.offer(1, 2, TimeUnit.SECONDS));
        System.out.println(arrayBlockingQueue.offer(2, 2, TimeUnit.SECONDS));
        System.out.println(arrayBlockingQueue.offer(3, 2, TimeUnit.SECONDS));
        System.out.println("3放入完成!");
        System.out.println("准备放4,当前时间:"+ DateUtil.now());
        System.out.println(arrayBlockingQueue.offer(4, 2, TimeUnit.SECONDS));
        System.out.println("4插入执行结束:当前时间->"+DateUtil.now());
    输出:
        true
        true
        true
        3放入完成!
        准备放4,当前时间:2021-08-06 15:16:13
        false
        4插入执行结束:当前时间->2021-08-06 15:16:15
    发现,出现问题后,不会抛出异常,会在插入出阻塞对应时间,再执行后续!

SynchronousQueue

一种阻塞队列,队列中只能存储一个元素,当这个元素被取出时,才能又放进去
方法:put/take
样例:
    public class SynchronousQueueDemo {
        public static void main(String[] args) {
            //重点1:创建SynchronousQueue的队列
            BlockingQueue<String> blockingQue = new SynchronousQueue<>();
            new Thread(() -> {
                for (int i = 0; i < 6; i++) {
                    try {
                        System.out.println(Thread.currentThread().getName() + "准备放入值...");
                        //重点2:SynchronousQueue队列里最多只能放一个元素后,这里会阻塞,直至消息被取出!
                        blockingQue.put(Thread.currentThread().getName() + "放入" + i);
                        System.out.println(Thread.currentThread().getName() + "放入值成功!");
                        TimeUnit.SECONDS.sleep(2);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }, "放线程").start();
    
            new Thread(() -> {
                for (int i = 0; i < 6; i++) {
                    try {
                        System.out.println(Thread.currentThread().getName() + "准备取出值...");
                        System.out.println(Thread.currentThread().getName() + "-->取出:" + blockingQue.take());
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }, "读线程").start();
        }
    }
输出:
    放线程准备放入值...
    读线程准备取出值...
    读线程-->取出:放线程放入0
    放线程放入值成功!
    读线程准备取出值...
    放线程准备放入值...
    放线程放入值成功!
    读线程-->取出:放线程放入1
    读线程准备取出值...
    放线程准备放入值...
    放线程放入值成功!
    读线程-->取出:放线程放入2
    读线程准备取出值...
    放线程准备放入值...
    放线程放入值成功!
    读线程-->取出:放线程放入3
    读线程准备取出值...
    放线程准备放入值...
    读线程-->取出:放线程放入4
    读线程准备取出值...
    放线程放入值成功!
    放线程准备放入值...
    放线程放入值成功!
    读线程-->取出:放线程放入5
结论发现:
    SynchronousQueue队列中只能放入一个元素,当这个元素被取出时,才能放入第二个元素!

 

posted @ 2022-05-13 21:07  努力的达子  阅读(35)  评论(0编辑  收藏  举报