浓浓棕情之自产自消

今天是端午节,祝大家端午节快乐。今年的疫情让很多人放弃了出行的计划,宅在家里,我也是无聊,想到写点什么东西和大家分享下,希望有感兴趣的看看,如果有什么想法欢迎交流。

生产者和消费者是软件世界里很寻常的场景,然而大多数程序员平时写代码不会用到,因为很多系统都是用来查询数据展示数据,写写CRUD就好了。随着MQ的横空出世,让大家都醉心于这种好用的中间件,配置一个Topic,发送消息就调用客户端的发送接口,接收消息继承一个接口,写一个Listener,整个从生产到消费全流程就这种友好的解决了,性能和完整性更不用你担心,因为这些主流MQ都号称是几十万的TPS,4个9的可靠性。

凡事需知其然及其所以然,MQ就是一个基于生产者和消费者的最佳实践。今天想基于阻塞队列来实现生产者和消费者的场景,阻塞队列用的是ArrayBlockingQueue,一个生产者线程,一个消费者线程。

生产者代码

public class Producer implements Runnable {
    BlockingQueue<Integer> queue;
    public Producer(BlockingQueue<Integer> queue) {
        this.queue = queue;
    }

    public void run() {
        while (true) {
            Integer num = Double.valueOf(Math.random()*100).intValue();
            this.queue.offer(num);
            System.out.println("加入元素到队列:"+num);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

消费者代码

public class Consumer implements Runnable {

    BlockingQueue<Integer> queue;

    String name;

    public Consumer(BlockingQueue<Integer> queue) {
        this.queue = queue;
    }

    public Consumer(String name, BlockingQueue<Integer> queue) {
        this.name = name;
        this.queue = queue;
    }

    public void run() {
        while (true){
            System.out.println("开始队列长度**********:"+queue.size());
            Integer num = this.queue.poll();
            System.out.println(name + "消费元素:**********" + num);
            System.out.println("结束队列长度:"+queue.size());
            try {
                Thread.sleep(120);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

下面创建了一个生产者和二个消费者,因为生产者生产得快,大家可以先用一个消费者看看结果,会发现消费队列总会有元素,主要源于生产者生产的速度比消费者快,当增加一个消费者后,就会发现队列为空,被消费完了,线程等待的状况。

public class ConsumerTest {
    public static void main(String[] args) {
        BlockingQueue<Integer> myQueue = new ArrayBlockingQueue<Integer>(1000);
        Thread producer = new Thread(new Producer(myQueue));
        Thread consumer = new Thread(new Consumer(myQueue));
        Thread consumer2 = new Thread(new Consumer("consumer2", myQueue));
        consumer.start();
        producer.start();
        consumer2.start();

        try {
            producer.join();
            consumer.join();
            consumer2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

如果队列满了,对于ArrayBlockingQueue 的 offer操作来说,会直接丢弃掉插入的元素。如果想验证,可以将队列容量修改为4,然后在生产者中加入下面的代码,就会打出插入失败的元素,并且往后看,会发现这个元素不会被消费到。

public void run() {
        while (true) {
            Integer num = Double.valueOf(Math.random()*100).intValue();

            String isSuccess = this.queue.offer(num) ? "成功":"失败";
            System.out.println("加入元素到队列:"+ num +" " + isSuccess );
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

今天和大家聊了下生产者和消费者,相信大家已经大致明白了整个的过程,为大家模拟了单生产者多消费者的例子,大家也可以自己去扩展多生产者和多消费者。说到这里,还是想抛砖引玉,这个队列例子和MQ队列相比有哪些不足,MQ有哪些黑科技为大型分布式系统保驾护航。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值