RabbitMQ基础篇(三)-RabbitMQ工作队列

工作队列(又称任务队列)的主要思想是为了避免立即执行资源密集型任务,而不得不等待他完成。其作用就是将需要处理的任务放在队列(先进先出)中,一个工作进程可以取出任务并完成工作。如果启动了多个工作进程,那么这些工作线程会一起处理这些任务。

好比工厂的流水线,如果流水线上有300个产品,而工位上只有一位工人在给产品加工,可想而知其效率低下。如果在流水线后多安排几个工位,那么就可以提高产品加工速度(注意:一个产品只能被加工一次,不能被多次处理,要防止重复“加工”)。

轮询发消息

概念

rabbitmq队列处理机制默认是轮询的,即轮流按工作顺序将任务分配给工作线程(循环分配任务)。

实例代码

生产者首先往队列中加入15条消息,成功加入队列后等待消费者消费。生产者代码如下:

public static final String QUEUE_NAME = "rabbit_queue";
public static void main(String[] args) throws IOException, TimeoutException {
        Connection connection = RabbitConnectionUtil.getConnection();
        // 获取信道
        Channel channel = connection.createChannel();
        for (int i = 0; i < 15; i++) {
            /**
             * 生成队列
             * queue 队列名称
             * durable 是否持久化
             * exclusive 是否独占队列
             * autoDelete 是否自动删除队列(服务器不再使用时自动删除队列)
             * arguments 队列参数
             */
            HashMap<String, Object> param = new HashMap<>();
            param.put("name", "梦尘");
            param.put("action", "添加了一个消息");
            channel.queueDeclare(QUEUE_NAME, false, false, false, param);

            /**
             * exchange 交换机
             * 路由的key值
             * 其他参数信息
             * 发送消息的消息体
             */
            String message = "给您发了一条消息";
            channel.basicPublish("", QUEUE_NAME, null, message.getBytes(StandardCharsets.UTF_8));
            System.out.println("消息发送完毕!");
        }
    }

创建5个消费者,监听到队列中有任务时进行工作。消费者代码如下:

public class Work01 implements Runnable {
    public static final String QUEUE_NAME = "rabbit_queue";

    public static void main(String[] args) {
        Runnable work01 = new Work01();
        new Thread(work01, "A").start();
        new Thread(work01, "B").start();
        new Thread(work01, "C").start();
        new Thread(work01, "D").start();
        new Thread(work01, "E").start();
    }

    @Override
    public void run() {
        try {
            String threadName = Thread.currentThread().getName();
            Connection connection = RabbitConnectionUtil.getConnection();
            Channel channel = connection.createChannel();
            // 消息接收
            DeliverCallback deliverCallback = (consumerTag, message) -> {
                System.out.println("Work01 => " + threadName + "接收到消息:" + new String(message.getBody()));
            };
            // 消息取消监听
            CancelCallback cancelCallback = (consumerTag) -> {
                System.out.println(consumerTag + "消息者取消消息发送!");
            };
            // 消息发送
            try {
                channel.basicConsume(QUEUE_NAME, true, deliverCallback, cancelCallback);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        } catch (IOException | TimeoutException e) {
            throw new RuntimeException(e);
        }
    }
}

运行结果:
可以看到里面成功添加了15条消息,接下来运行消费者查询观察消费过程。

消费者运行结果:

总结

工作队列是学习RabbitMQ的一个非常重要知识点,通过利用队列的先进先出的特点,将工作顺序分配给工作线程执行。

思考

如果D任务在被消费者处理过程中因某些原因出现bug导致任务中断,而这时候队列已经将任务分配出去并清除了队列里的任务D,这就意味着我们丢失了这条未处理完毕的任务,那么我们该怎么防止任务丢失的情况?

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值