通过两种方式手写一个消息队列


参考每特教育蚂蚁课堂

1.基于多线程的方式实现MQ(极简纯享版)

MQ就是在消费者服务和生产者服务传递信息的通道,生产者向队列中投递消息,然后消费者过来取。所以我们可以这样设计,用一个队列作为中间件,然后开启两个线程,一个是生产者线程,一个是消费者线程,生产者线程向队列中插入json串,消费者线程过来取这个就是一个简单的MQ的实现。

    private static LinkedBlockingDeque<JSONObject> msgs = new LinkedBlockingDeque<JSONObject>();

    public static void main(String[] args) {
   
        // 生产线程
        Thread producerThread = new Thread(new Runnable() {
   
            @Override
            public void run() {
   
                try {
   
                    while (true) {
   
                        Thread.sleep(1000);
                        JSONObject data = new JSONObject();
                        data.put("wjz", "nb");
                        // 存入消息
                        msgs.offer(data);
                    }
                } catch (Exception e) {
   

                }

            }
        }, "生产者");
        producerThread.start();
        // 消费者线程
        Thread consumerThread  = new Thread(new Runnable() {
   
            @Override
            public void run() {
   
                try {
   
                    while (true) {
   
                        JSONObject data = msgs.poll();
                        if (data != null) {
   
                            System.out.println(LocalTime.now() + Thread.currentThread().getName() + "," + data);
                        }
                    }

                } catch (Exception e) {
   

                }

            }
        }, "消费者");
        consumerThread.start();
    }

我们可以看到每隔1s生产者就会向消息队列中投放消息,消费者不断接收消息并打印结果,

在这里插入图片描述

如图所示大概是每隔1s消费者接收到消息。

这里面我们要注意的是不能用普通队列,必须用阻塞队列,因为阻塞队列当队列有东西的时候回自动触发消费者线程从队列里取东西,当队列为空的时候会自动触发生产者线程往里面放东西。如果用普通队列的话就会一直往队列里放东西而没有取东西,所以他会阻塞在生产者线程,不会进行线程之间的切换。

在这里插入图片描述

2.基于网络通讯的方式实现MQ

我们可以基于Netty实现一个MQ,首先我要有一个MQ服务端用来接收连接以及推送消息。

public class MayiktNettyMQServer {
   
    public void bind(int port) throws Exception {
   
        /**
         * Netty 抽象出两组线程池BossGroup和WorkerGroup
         * BossGroup专门负责接收客户端的连接, WorkerGroup专门负责网络的读写。
         */
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        ServerBootstrap bootstrap = new ServerBootstrap();
        try {
   
            bootstrap.group(bossGroup, workerGroup)
                    // 设定NioServerSocketChannel 为服务器端
                    .channel(NioServerSocketChannel.class)
                    //BACKLOG用于构造服务端套接字ServerSocket对象,标识当服务器请求处理线程全满时,
                    //用于临时存放已完成三次握手的请求的队列的最大长度。如果未设置或所设置的值小于1,Java将使用默认值50。
                    .option(ChannelOption.SO_BACKLOG, 100)
                    // 服务器端监听数据回调Handler
                    .childHandler(new MayiktNettyMQServer.ChildChannelHandler());
            //绑定端口, 同步等待成功;
            ChannelFuture future = bootstrap.bind(port).sync();
            System.out.println("当前服务器端启动成功...");
            //等待服务端监听端口关闭
            future
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

温JZ

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

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

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

打赏作者

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

抵扣说明:

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

余额充值