RabbitMQ 学习:Work Queues 轮询(工作队列)

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

相反我们安排任务在之后执行。我们把任务封装为消息并将其发送到队列。

在后台运行的工作进程将弹出任务并最终执行作业。

当有多个工作线程时,这些工作线程将一起处理这些任务。工作线程就相当于消费者

        当生产者给队列发送大量消息(非常多,超级多)时,此时很多消息停留在队列当中无法被一个或多个线程(消费者)及时的处理,这时候会考虑增加线程(消费者),由原来的单一线程(消费者)调整为多个线程(消费者),但是又要遵循一个原则(一个消息只能被处理一次,避免重复消费)。

        而rabbitmq的工作队列(又叫任务队列)就有一个特点叫轮询分发消息,采用轮询机制给各处理线程分发消息,保证每个消息都会被消费并且只被消费一次,从而达到避免重复分发消息的目的。各处理线程(消费者)之间是竞争关系,轮流抢夺消费信息。

RabbitMQ 学习:Work Queues 轮询(工作队列)_第1张图片

 工作队列代码实现:

一、创建工具类

package com.zzuli.rabbitmq.utils;

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

/**
 * @Author WangXiaoSong
 * @Date 2023/4/11 21:42
 * @Description 此类为连接工厂创建信道的工具类
 */
public class RabbitMqUtils {

    public static Channel getChannel() throws Exception{
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("192.168.80.132");
        factory.setUsername("admin");
        factory.setPassword("root");
        factory.setVirtualHost("/");

        Connection connection = factory.newConnection();
        return connection.createChannel();
    }
}

二、创建工作线程

package com.zzuli.rabbitmq.two;

import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;
import com.rabbitmq.client.Delivery;
import com.zzuli.rabbitmq.utils.RabbitMqUtils;

/**
 * @Author WangXiaoSong
 * @Date 2023/4/11 21:47
 * @Description 这是一个工作线程(相当于之前的消费者)
 */
public class Worker01 {

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

    //接收消息
    public static void main(String[] args) throws Exception{
        //获取通道
        Channel channel = RabbitMqUtils.getChannel();

        //接收消息回调
        DeliverCallback callback = (String var1, Delivery var2) ->{
            System.out.println("接收到的消息:" + new String(var2.getBody()));
        };

        //消息被中断接收回调
        CancelCallback cancelCallback = (String var1) ->{
            System.out.println(var1 + "消息被消费者取消消费接口回调逻辑");
        };
        System.out.println("C2等待接收消息...");
        //消息的接收
        channel.basicConsume(QUEUE_NAME,true,callback,cancelCallback);
    }
}

 三、创建生产者队列

package com.zzuli.rabbitmq.two;

import com.rabbitmq.client.Channel;
import com.zzuli.rabbitmq.utils.RabbitMqUtils;

import java.util.Scanner;

/**
 * @Author WangXiaoSong
 * @Date 2023/4/11 22:16
 * @Description 生产者 发送大量消息
 */
public class Task01 {

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

    public static void main(String[] args) throws Exception{
        //获取channel
        Channel channel = RabbitMqUtils.getChannel();
        /**
         * 生成一个队列
         * 1.队列名称
         * 2.队列中消息是否持久化(磁盘) 默认存储在内存中
         * 3.队列是否只供多个消费者消费(是否可进行消息共享),true多个,false一个
         * 4.是否自动销毁 最后一个消费者断开连接后,该队列是否自动销毁  true销毁,false不销毁
         * 5.关于延迟消息、死信消息等设置
         */
        channel.queueDeclare(QUEUE_NAME,false,false,false,null);
        //从控制台输入要发送的消息
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()){
            String message = scanner.next();
            /**
             * 1.发送到哪个交换机上(使用哪个交换机)
             * 2.路由key(本次队列名)
             * 3.某些参数
             * 4.二进制形式的消息
             */
            channel.basicPublish("",QUEUE_NAME,null,message.getBytes());
            System.out.println(message + "消息已发送");
        }

    }


}

四、idea设置进程多开模式

RabbitMQ 学习:Work Queues 轮询(工作队列)_第2张图片

RabbitMQ 学习:Work Queues 轮询(工作队列)_第3张图片 

RabbitMQ 学习:Work Queues 轮询(工作队列)_第4张图片 

五、为了便于区分,启动Worker01中的main方法之后,将 print中的C1改为C2再次启动

RabbitMQ 学习:Work Queues 轮询(工作队列)_第5张图片

六、启动Task01,依次发送AA  BB  CC  DD四个消息,查看Worker01的两个进程的运行情况

RabbitMQ 学习:Work Queues 轮询(工作队列)_第6张图片 

RabbitMQ 学习:Work Queues 轮询(工作队列)_第7张图片 

RabbitMQ 学习:Work Queues 轮询(工作队列)_第8张图片 

结论:通过此次测试,得出rabbitmq的工作队列是轮询发送消息的,多个消费者之间是竞争(抢占)关系。 

 

你可能感兴趣的:(rabbitmq,java,开发语言)