JUC(6)——阻塞队列

阻塞队列

1.什么是阻塞队列?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p7IzPIyN-1621378757606)(C:\Users\ThinkPad\AppData\Roaming\Typora\typora-user-images\image-20210327011406739.png)]

顾名思义,阻塞队列就是一个队列,如图,线程1向队列中添加元素,而线程2从队列中移除元素;

当队列满时,向队列中添加元素时就会阻塞,直至其他线程从队列中移除元素;当队列空时,从队列中移除元素时就会阻塞,直至其他元素向队列中添加元素;

2.为什么要使用阻塞队列?

在concurrent包发布之前,需要认为的控制线程的阻塞与唤醒;但随着concurrent包的发布,我们使用阻塞队列时,不用再去担心线程的阻塞与唤醒,这一切全部被阻塞队列包办了。

3.阻塞队列的分类

  • ArrayBlockingQueue 由数组组成的有界阻塞队列
  • LinkedBlockingQueue 由链表组成的有界阻塞队列<但其大小默认值为Integer.MAX_VALUE>
  • SyschronousQueue 不存储元素的阻塞队列(零库存),单个元素的阻塞队列,也就是生产 一个消费一个
  • PriorityBlockingQueue 支持优先级排序的无界阻塞队列
  • DelayQueue 使用优先级队列实现的延时无界阻塞队列
  • LinkedTransferQueue 由链表组成的无界阻塞队列
  • LinkedBlockingDueue 由链表组成的双向阻塞队列

4.阻塞队列的核心用法

方法类型抛出异常返回布尔阻塞超时
插入add(E e)offer(E e)put(E e)offer(E e,Time,TimeUnit)
移除remove()poll()take()poll(Time,TimeUnit)
检查element()peek()

4.1抛出异常

  • 当阻塞队列满时,再往队列里add插入元素会抛IllegalStateException:Queue full
    public static void main(String[] args) {
        BlockingQueue<Integer> blockingQueue1 = new ArrayBlockingQueue<>(3);
        System.out.println(blockingQueue1.add(1));
        System.out.println(blockingQueue1.add(2));
        System.out.println(blockingQueue1.add(3));
        System.out.println(blockingQueue1.add(4));
        
//        System.out.println(blockingQueue1.element());
//        System.out.println(blockingQueue1.remainingCapacity());
        
//        System.out.println(blockingQueue1.remove());
//        System.out.println(blockingQueue1.remove());
//        System.out.println(blockingQueue1.remove());
        
//        System.out.println(blockingQueue1.element());
//        System.out.println(blockingQueue1.remainingCapacity());
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2QMm5sQK-1621378757608)(C:\Users\ThinkPad\AppData\Roaming\Typora\typora-user-images\image-20210327014335639.png)]

  • 当阻塞队列空时,再往队列里remove移除元素会抛NoSuchElementException
    public static void main(String[] args) {
        BlockingQueue<Integer> blockingQueue1 = new ArrayBlockingQueue<>(3);

        blockingQueue1.add(1);
        blockingQueue1.add(2);
        blockingQueue1.add(3);
//        System.out.println(blockingQueue1.add(4));
        
//        System.out.println(blockingQueue1.element());
//        System.out.println(blockingQueue1.remainingCapacity());
        
        System.out.println(blockingQueue1.remove());
        System.out.println(blockingQueue1.remove());
        System.out.println(blockingQueue1.remove());
        
        System.out.println(blockingQueue1.element());
//        System.out.println(blockingQueue1.remainingCapacity());
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fHdxUVEv-1621378757610)(C:\Users\ThinkPad\AppData\Roaming\Typora\typora-user-images\image-20210327015249383.png)]

4.2返回布尔

  • 插入方法,成功 ture 失败 false

  • 移除方法,成功返回出队列的元素,队列里面没有就返回null

    public static void main(String[] args) {
        BlockingQueue<Integer> blockingQueue1 = new ArrayBlockingQueue<>(3);

        System.out.println(blockingQueue1.offer(1));
        System.out.println(blockingQueue1.offer(2));
        System.out.println(blockingQueue1.offer(3));
        System.out.println(blockingQueue1.offer(4));
        System.out.println(blockingQueue1.peek());

        System.out.println(blockingQueue1.poll());
        System.out.println(blockingQueue1.poll());
        System.out.println(blockingQueue1.poll());
        System.out.println(blockingQueue1.poll());
        System.out.println(blockingQueue1.peek());
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1fdygttD-1621378757611)(C:\Users\ThinkPad\AppData\Roaming\Typora\typora-user-images\image-20210327020108538.png)]

4.3一直阻塞

  • 当阻塞队列满时,生产者线程继续往队列里put元素,队列会一直阻塞生产线程直到put数据成功或者响应中断退出。

  • 当阻塞队列空时,消费者线程试图从队列里take元素,队列会一直阻塞消费者线程直到队列可用。

    public static void main(String[] args) throws InterruptedException {
            BlockingQueue<Integer> blockingQueue1 = new ArrayBlockingQueue<>(3);
            blockingQueue1.put(1);
            blockingQueue1.put(2);
            blockingQueue1.put(3);
            System.out.println(blockingQueue1.take());
            System.out.println(blockingQueue1.take());
            System.out.println(blockingQueue1.take());
            System.out.println(blockingQueue1.take());
        }
    

4.4超时退出

当阻塞队列满时,队列会阻塞生产者线程一定时间,超过后限时后生产者线程会退出

    public static void main(String[] args) throws InterruptedException{
        BlockingQueue<Integer> blockingQueue1 = new ArrayBlockingQueue<>(3);

        System.out.println(blockingQueue1.offer(1, 2, TimeUnit.SECONDS));
        System.out.println(blockingQueue1.offer(1, 2, TimeUnit.SECONDS));
        System.out.println(blockingQueue1.offer(1, 2, TimeUnit.SECONDS));
        System.out.println(blockingQueue1.offer(1, 2, TimeUnit.SECONDS));
    }

4.5SyschronousQueue

    public static void main(String[] args) throws InterruptedException{
        BlockingQueue blockingQueue = new SynchronousQueue();

        new Thread(()->{
            try {
                blockingQueue.put(1);
                blockingQueue.put(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"AAA").start();

        new Thread(()->{
            try {
                Thread.sleep(3000);
                System.out.println(blockingQueue.take());
                Thread.sleep(3000);
                System.out.println(blockingQueue.take());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"BBB").start();
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SONNIE在路上

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值