安杰小讲堂之阻塞队列

德华:嫂子,为什么会有阻塞队列呢?
安杰:它的产生主要有两个原因,一个是“不得不”,另一个是“应该有”。

不得不:就像我们去银行排队取钱,当没有提供给你的窗口的时候,我们就需要坐在小板凳上,看着《父母爱情》。
应该有:比如说经营一家餐厅,我们当然希望自己准备的餐桌永远都不空,当没有餐桌的时候,就让顾客先等一会儿。

下面是详细介绍
在这里插入图片描述
那么它的出现对我们有什么好处呢?
在这里插入图片描述
我们不在需要自己去控制那些细节,BlockingQueue就能帮我们搞定它。
在这里插入图片描述

现在看它怎么用:
我们以ArrayBlockingQueue为例
首先大家结合下面的代码,大家来看看这个表
在这里插入图片描述
add,remove,element


BlockingQueue<String> blockingQueue =new ArrayBlockingQueue<>(3);
           System.out.println( blockingQueue.add("a"));
            System.out.println(blockingQueue.add("b"));
            System.out.println(blockingQueue.add("c"));
            System.out.println(blockingQueue.add("x"));
            System.out.println(blockingQueue.element());

            System.out.println(blockingQueue.remove());
            System.out.println(blockingQueue.remove());
            System.out.println(blockingQueue.remove());
          
结果:
true
true
true
Exception in thread "main" java.lang.IllegalStateException: Queue full
	at java.base/java.util.AbstractQueue.add(AbstractQueue.java:98)
	at java.base/java.util.concurrent.ArrayBlockingQueue.add(ArrayBlockingQueue.java:326)

这是一个add超限的实现,同样当remove超限也会报错。

  System.out.println( blockingQueue.offer("a"));
        System.out.println(blockingQueue.offer("b"));
        System.out.println(blockingQueue.offer("c"));

        System.out.println(blockingQueue.offer("x"));


        System.out.println(blockingQueue.peek());

        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
         System.out.println(blockingQueue.poll());
   结果:
    true
	true
	true
	false
	a
	a
	b
	c
	null

可以看出,offer和poll还有peek都是很有礼貌的方法,满或空的时候,都会告诉你你的操作成功与否,而不像add他们几个,直接给你抛出一个异常这么暴力。

下面是put和take


import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class BQDemo2 {
    public static void main(String[] args) throws InterruptedException {
        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue(3);
        blockingQueue.put("2");
        blockingQueue.put("3");
        blockingQueue.put("4");
        System.out.println("----------------------");

        blockingQueue.put("9");
        
        System.out.println("----------------------");
        blockingQueue.take();
        blockingQueue.take();
        blockingQueue.take();

    }
}

结果

----------------------

并且此时运行并没有停止,所以是运行到了第四个put时main线程被阻塞了。

下面这个是另外offer和poll加了参数。

	    blockingQueue.offer("1",2, TimeUnit.SECONDS);
        blockingQueue.offer("1",2, TimeUnit.SECONDS);
        blockingQueue.offer("1",2, TimeUnit.SECONDS);
        blockingQueue.offer("1",2, TimeUnit.SECONDS);
        System.out.println("------=========--------");
        blockingQueue.poll(2, TimeUnit.SECONDS);
        blockingQueue.poll(2, TimeUnit.SECONDS);
        blockingQueue.poll(2, TimeUnit.SECONDS);
        blockingQueue.poll(2, TimeUnit.SECONDS);
        System.out.println("=======-------========");
        

结果

------=========--------
=======-------========

总结一下:
add,remove,element都是直接率性的性格,你只要有错他们会给你一个重重的教训。
offer,poll 不设置参数的的时候是友好的,当你有错时,他们只会提醒你你出错了。
put,take 是死脑筋,你告诉它我要插入或取出时,当满或空时,它就会一直等你。
而设置了参数的offer,poll 就像是已经明智的小朋友,有自己的思考,有耐心,有底线,会先等你,如果超过他的底线了,才会告诉你false。
在这里插入图片描述

下面是一个生产者消费者的实现。


import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public  class PCDemo  {
    static int num =0;
    Lock lock= new ReentrantLock();
    public Condition condition=lock.newCondition();
    public  void  increase() throws Exception {
        lock.lock();
        try {
            while (num!=0){
                System.out.println("等待消费"+num);
                condition.await();
            }
            num++;
            condition.signalAll();
            System.out.println("生产一个,此时num="+num);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }



    }
    public  void  decrease() throws Exception {
        lock.lock();
        try {
            while (num==0){
                System.out.println("等待生产 "+num);
                 condition.await();
            }
            num--;
            condition.signalAll();
            System.out.println("消费一个,此时num="+num);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }

    }

    public static void main(String[] args) {
        PCDemo pcDemo =new PCDemo();
        new Thread(()->{
            try {
                for (int i = 0;i<5;i++){
                pcDemo.increase();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        },"AAA" ).start();
        new Thread(()->{
            try {
                for (int i = 0;i<5;i++) {
                    pcDemo.decrease();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        },"BBB" ).start();
    }
}

结果

生产一个,此时num=1
等待消费1
消费一个,此时num=0
等待生产 0
生产一个,此时num=1
等待消费1
消费一个,此时num=0
等待生产 0
生产一个,此时num=1
等待消费1
消费一个,此时num=0
等待生产 0
生产一个,此时num=1
等待消费1
消费一个,此时num=0
生产一个,此时num=1
消费一个,此时num=0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值