消息中间件 RabbitMQ 之 Work Queues(工作队列)

Work Queues 工作队列

工作队列(又称任务队列)的主要思想是避免立即执行资源密集型任务,而不得不等待它完成的情况。

相反我们安排任务在之后执行。把任务封装为消息并将其发送给到队列。在后台运行的工作进程将弹出任务并最终执行作业。当有多个工作线程时,这些工作线程将一起处理这些任务。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CQrG1s84-1649755339864)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220411193456254.png)]

3.1 轮训分发消息


​ 在这个案例中我们会启动两个线程,一个消息发送线程,我们来看看这两个工作线程是如何工作的

3.1.1 抽取工具类


将单一不变的操作提取出来,成为工具类,方便使用

代码如下:

package com.example.utils;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

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

/**
 * @author qie ting feng yin
 * @version 1.0
 * @description: 连接工程创建信道的工具类
 * @date 2022/4/12 0012 9:53
 */
public class RabbitUtils {

    //得到一个连接的channel
    public static Channel getChannel() throws IOException, TimeoutException {
        //创建一个连接工厂
        ConnectionFactory connectionFactory = new ConnectionFactory();
        //工厂ip 连接RabbitMQ队列
        connectionFactory.setHost("47.98.241.39");
        //用户名
        connectionFactory.setUsername("admin");
        //密码
        connectionFactory.setPassword("123456");
        //创建连接
        Connection connection = connectionFactory.newConnection();
        //创建信道(生产者通过信道连接队列)
        return connection.createChannel();
    }
}

3.1.2 启动两个工作线程


编写程序,并行执行两次程序,来模拟两次工作线程,执行两次的方式:

  1. IDEA左上角打开Edit Configurations
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cAtYgweq-1649755339865)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220412165154069.png)]

  2. 找到Modify options并点击
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CGMgcuFa-1649755339865)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220412165515338.png)]

  3. 选择Allow multiple instances,并点击apply

代码如下:

package com.example.two;

import com.example.utils.RabbitUtils;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;

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

/**
 * @author qie ting feng yin
 * @version 1.0
 * @description: 一个工作线程(相当于消费者)
 * @date 2022/4/12 0012 10:09
 */
public class Work01 {

    //队列的名称
    public static final String QUEUE_NAME = "hello";

    //接收消息
    public static void main(String[] args) throws IOException, TimeoutException {

        //获取信道
        Channel channel = RabbitUtils.getChannel();

        //声名  消费者成功消费(接收)消息的回调(消息接收成功时执行)
        DeliverCallback deliverCallback = (consumerTag, message) -> {
            //打印消息体
            System.out.println("消费者成功消费消息,消息体为:"+new String(message.getBody()));
        };
        //声名  消费者取消消费消息时的回调(消息接收被取消时执行)
        CancelCallback cancelCallback = consumerTag -> {
            System.out.println(consumerTag+"消息消费被中断");
        };

        /**
         * 消费者消费(接收)消息,参数含义如下:
         *    1.消费哪个队列
         *    2.消费之后是否要自动应答
         *    3.消费者成功消费消息的回调
         *    4.消费者取消消费消息的回调
         */
        /* 并行执行模拟两个工作线程,轮训(彼此交互)接收大量消息
        第一次执行
        System.out.println("work01等待接收消息...");*/
        //第二次执行
        System.out.println("work02等待接收消息...");
        channel.basicConsume(QUEUE_NAME,true,deliverCallback,cancelCallback);
    }
}

执行结果如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EHFVjSCF-1649755339866)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220412165956512.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IyM2evIA-1649755339867)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220412170101662.png)]

此时没有发送消息,所以两个工作线程只是等待消息

3.1.3 启动一个发送线程


编写生产者代码,模拟发送大量消息

代码如下:

package com.example.two;

import com.example.utils.RabbitUtils;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;

import java.io.IOException;
import java.util.Scanner;
import java.util.concurrent.TimeoutException;

/**
 * @author qie ting feng yin
 * @version 1.0
 * @description: 生产者  发送大量消息
 * @date 2022/4/12 0012 11:18
 */
public class Task01 {

    //队列名称
    public static final String QUEUE_NAME = "hello";

    //发送消息
    public static void main(String[] args) throws IOException, TimeoutException {

        //获取信道
        Channel channel = RabbitUtils.getChannel();

        //声名  消费者成功消费(接收)消息的回调
        DeliverCallback deliverCallback = (consumerTag, message) -> {
            //打印消息体
            System.out.println("消费者成功消费消息,消息体为:"+new String(message.getBody()));
        };
        //声名  消费者取消消费消息时的回调
        CancelCallback cancelCallback = consumerTag -> {
            System.out.println("消息消费被中断");
        };

        /**
         * 生成一个队列,参数的含义如下:
         *      1.队列名称
         *      2.队列里面的消息是否持久化(存储在磁盘上),默认情况false(存储在内存中)
         *      3.该队列是否进行消息共享,默认false
         *      4.是否自动删除,最后一个消费者断开连接后,该队列是否自动删除
         *      5.其他参数
         */
        channel.queueDeclare(QUEUE_NAME,false,false,false,null);

        //发消息,从控制台中接收消息并发送
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()){
            String message = scanner.next();
            channel.basicPublish("",QUEUE_NAME,null,message.getBytes());
            System.out.println("发送消息完成:"+message);
        }
    }
}

执行代码并模拟发送大量消息:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UPNG0cCI-1649755339869)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220412170638030.png)]

3.1.4 结果展示


查看两个工作线程的接收消息的情况,结果如下:

  • 第一个工作线程的接收情况:
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RlqEQf2H-1649755339869)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220412170929470.png)]

  • 第二个工作线程的接收情况
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7JA7fSJM-1649755339870)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220412171051543.png)]

​ 小结:由两个工作线程接收消息的情况来看,首个消息的接受是随机的,但是后面的消息会轮流被线程接收,这就是 Work Queues(工作队列)的分发消息的方式——轮训分发消息

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值