RabbitMQ消息模型之Work消息模型

Work消息模型

复制代码
* work模型:
*      多个消费者消费同一个队列中的消息,每个消费者获取到的消息唯一,且只能消费一次
*      作用:提高消息的消费速度,避免消息的堆积
*      默认采用轮询的方式分发消息
*      如果某个消费者处理消息慢,会导致消息堆积
生产者
java 复制代码
package com.example.demo02.mq.work;

import com.example.demo02.mq.util.ConnectionUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * @author Allen
 * 4/10/2024 9:37 PM
 * @version 1.0
 * @description: work模式发送者
 *
 * work模型:
 *      多个消费者消费同一个队列中的消息,每个消费者获取到的消息唯一,且只能消费一次
 *      作用:提高消息的消费速度,避免消息的堆积
 *      默认采用轮询的方式分发消息
 *      如果某个消费者处理消息慢,会导致消息堆积
 */
public class WorkSender {
    public static void main(String[] args) throws Exception {
//        1:获取连接
        Connection connection = ConnectionUtils.getConnection();
//        2:创建通道
        Channel channel = connection.createChannel();
//        3:声明队列
        // 参数1:队列名称 参数2:是否持久化 参数3:是否排他性 参数4:是否自动删除 参数5:队列的属性
        channel.queueDeclare("work.queue", false, false, false, null);
//        4:发送100条消息
for (int i = 0; i < 100; i++) {
            String msg = "work模式消息" + i;
            //休眠i*5毫秒
            TimeUnit.MILLISECONDS.sleep(i * 5);
            // 参数1:交换机名称 参数2:队列名称 参数3:消息的其他属性 参数4:消息的内容
            channel.basicPublish("", "work.queue", null, msg.getBytes());
            System.out.println("work模式发送消息:" + msg);
        }
//        5:关闭通道
        channel.close();
//        6:关闭连接
        connection.close();
    }
}
消费者1

(能者多劳角色)

java 复制代码
package com.example.demo02.mq.work;

import com.example.demo02.mq.util.ConnectionUtils;
import com.rabbitmq.client.*;

import java.io.IOException;

/**
 * @author Allen
 * 4/10/2024 9:37 PM
 * @version 1.0
 * @description: work模式消费者1号
 */
public class WorkReciver1 {
    public static void main(String[] args) throws Exception {
        // 1:获取连接
        Connection connection = ConnectionUtils.getConnection();
        // 2:创建通道
        Channel channel = connection.createChannel();
        // 3:声明队列
        // 参数1:队列名称 参数2:是否持久化 参数3:是否排他性 参数4:是否自动删除 参数5:队列的属性
        channel.queueDeclare("work.queue", false, false, false, null);
        // 4:定义消费者,消费消息
        // 参数1:队列名称 参数2:是否自动确认消息 参数3:消费者对象
        Consumer consumer = new DefaultConsumer(channel) {
            // 消费者接收消息调用此方法
            // 参数1:消费者标签 参数2:队列参数 参数3:消息属性 参数4:消息内容
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                // 获取消息
                String msg = new String(body);
                System.out.println("work模式消费者1号接收消息:" + msg);
                channel.basicAck(envelope.getDeliveryTag(), false);
            }
        };
        channel.basicConsume("work.queue", false, consumer);

    }
}
消费者2

(消费能力差)

java 复制代码
package com.example.demo02.mq.work;

import com.example.demo02.mq.util.ConnectionUtils;
import com.rabbitmq.client.*;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * @author Allen
 * 4/10/2024 9:37 PM
 * @version 1.0
 * @description: work模式消费者1号
 */
public class WorkReciver2 {
    public static void main(String[] args) throws Exception {
        // 1:获取连接
        Connection connection = ConnectionUtils.getConnection();
        // 2:创建通道
        Channel channel = connection.createChannel();
        // 3:声明队列
        // 参数1:队列名称 参数2:是否持久化 参数3:是否排他性 参数4:是否自动删除 参数5:队列的属性
        channel.queueDeclare("work.queue", false, false, false, null);
            //如果此消费者性能较差,配置能者多劳:指定一次获取几条信息,消息消费成功后 ack之后 mq才会发送下一条消息
            channel.basicQos(1);
        // 4:定义消费者,消费消息
        // 参数1:队列名称 参数2:是否自动确认消息 参数3:消费者对象
        Consumer consumer = new DefaultConsumer(channel) {
            // 消费者接收消息调用此方法
            // 参数1:消费者标签 参数2:队列参数 参数3:消息属性 参数4:消息内容
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    //模拟二号消费者处理消息慢
                    try {
                        TimeUnit.SECONDS.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    // 获取消息:执行业务
                    String msg = new String(body);
                    System.out.println("work模式消费者2号接收消息:" + msg);
                    channel.basicAck(envelope.getDeliveryTag(), false);
            }
        };
        // 参数1:队列名称 参数2:ACK是否自动确认 参数3:消费者对象
        //必须手动确认消息,否则会报406错误
        channel.basicConsume("work.queue", false, consumer);

    }
}
结果:

能者多劳

相关推荐
喝汽水的猫^几秒前
Java实现Excel 导出(多 Sheet、复杂格式)
java·excel
毕设源码-朱学姐12 分钟前
【开题答辩全过程】以 基于JavaWeb的疾病查询系统的设计与实现为例,包含答辩的问题和答案
java·eclipse
雨中飘荡的记忆14 分钟前
Java面向对象编程详解
java·开发语言
zhangyifang_00924 分钟前
Spring中的BeanFactory类
java·后端·spring
大学生资源网26 分钟前
java毕业设计之面向校园的助力跑腿系统设计与实现源码(源码+文档+数据库)
java·数据库·mysql·毕业设计·源码·springboot
Wang's Blog1 小时前
RabbitMQ: 消息发送、连接管理、消息封装与三种工程方案
linux·ubuntu·rabbitmq
quikai19811 小时前
python练习第六组
java·前端·python
222you1 小时前
线程的常用方法
java·开发语言
是梦终空1 小时前
JAVA毕业设计259—基于Java+Springboot+vue3工单管理系统的设计与实现(源代码+数据库+开题报告)
java·spring boot·vue·毕业设计·课程设计·工单管理系统·源代码
用户2190326527351 小时前
Spring Boot 集成 Redis 实现看门狗 Lua 脚本分布式锁
java·后端