二.多个消费者同时消费一个列队

提供者的pom.xml和消费者的pom.xml和第一章一样
一.Producer提供者
发送消息的类:MessageSender.java

package com.rabbitmq.producer;

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

public class MessageSender {

    private Logger logger = LoggerFactory.getLogger(MessageSender.class);

    //声明一个列队名字
    private final static String QUEUE_NAME = "hello";

    /**
     * 多个消费者同时消费一个列队测试
     * 发送者不停的往MQ中发送消息
     * @param message
     * @return
     */
    public boolean sendMessageMany(String message){
        //new一个rabbitmq的连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        //设置需要连接的RabbitMQ的机器的地址,这里指向本机
        factory.setHost("localhost");
        //连接器
        Connection connection = null;
        //通道
        Channel channel = null;
        try {
            //尝试获取一个连接
            connection = factory.newConnection();
            //尝试创建一个通道
            channel = connection.createChannel();
            /*声明一个列队:
             * 1.queue队列的名字,是否持久化 为true则在rabbitMQ重启后生存,
             * 2.是否是排他性队列(别人看不到),只对当前连接有效,当前连接断开后,队列删除(设置了持久化也删除)
             * 3.自动删除,在最后一个连接断开后删除队列
             * 4.其他参数
             * */
            channel.queueDeclare(QUEUE_NAME,false,false,false,null);
            /*发布消息,注意这里调用了getBytes(),发送的其实是byte数组,接收方收到消息后,需要重新组装成String
             * 1.交换模式
             * 2.控制消息发送到哪个队列
             * 3.其他参数
             * 4.body 消息,byte数组
             * */
            //循环往列队发布消息
            int i = 0;
            String oldMessage = message;
            while(true){
                message+=i++;
                channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
                logger.info("已发送:"+message);
                try {
                    Thread.sleep(500);//500毫秒发送一次
                } catch (InterruptedException e) {
                    logger.info("线程被打断:"+message);
                }
                message=oldMessage;//还原消息
                //此代码没用,只是为了死循环出现防止编译出错
                if(!"q".equals("q")){
                    break;
                }
            }
            //关闭通道和链接(先关闭通道在关闭连接)
            channel.close();
            connection.close();
        } catch (IOException e) {
            logger.error("IO异常:"+e);
            return false;
        } catch (TimeoutException e){
            logger.error("超时异常:"+e);
            return false;
        }
        return true;
    }
}

2.测试发送消息的Main:ManySenderMain.java

package com.rabbitmq.main;

import com.rabbitmq.producer.MessageSender;

public class ManySenderMain {

    public static void main(String[] args) {
        MessageSender messageSender = new MessageSender();
        messageSender.sendMessageMany("hellow tiglle");
    }

}

二.Consumer消费者:

1.接收消息的消费者类:

package com.rabbitmq.consumer;

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;


public class MessageRecive {

    private Logger logger = LoggerFactory.getLogger(MessageRecive.class);

    //多个消费者消费消息:增加了是哪个消费者的标记
    public boolean manyConsume(String queueName,final String flag){
        //连接rabbitmq
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = null;
        Channel channel =null;

        //声明消费的queue
        try {
            connection = factory.newConnection();
            channel = connection.createChannel();

            channel.queueDeclare(queueName,false,false,false,null);
            //这里重写了DefaultConsumer的handleDelivery方法,因为发送的时候对消息进行了getByte(),在这里要重新组装成String
            Consumer consumer = new DefaultConsumer(channel){
                //重写父类方法
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body)throws IOException {
                    String message = new String(body, "UTF-8");
                    logger.info("["+flag+"]接收到:" + message);
                }
            };
            //上面是声明消费者,这里用 声明的消费者  消费  列队的消息
            channel.basicConsume(queueName, true,consumer);
            //这里不能关闭连接,调用了消费方法后,消费者会一直连接着rabbitMQ等待消费
        } catch (Exception e) {
            logger.error("出现异常:"+e);
            return false;
        }
        return true;
    }

}

3.测试启动多个消费者开始监听消费消息的Main方法:ManyReviceMain.java

package com.rabbitmq.main;

import com.rabbitmq.consumer.MessageRecive;

//多个消费之同时消费列队的消息
public class ManyReviceMain {

    //这个队列名字要和生产者中的名字一样,否则找不到队列
    private final static String QUEUE_NAME = "hello";

    /**
     * 测试多个客户端消费提供者的消息
     * 可以看出消息会平均发送个每个消费者
     * RabbitMQ的特性,称作“Round-robin dispatching”,消息会平均的发送给每一个消费者
     * @param args
     */
    public static void main(String[] args) {
        MessageRecive messageRecive1 = new MessageRecive();
        messageRecive1.manyConsume(QUEUE_NAME, "consumer1");
        MessageRecive messageRecive2 = new MessageRecive();
        messageRecive2.manyConsume(QUEUE_NAME, "consumer2");
        MessageRecive messageRecive3 = new MessageRecive();
        messageRecive3.manyConsume(QUEUE_NAME, "consumer3");
        MessageRecive messageRecive4 = new MessageRecive();
        messageRecive4.manyConsume(QUEUE_NAME, "consumer4");
    }

}

可以看到,提供者不停的发送消息,四个消费者是平均规律的分摊了消费者的消息。
RabbitMQ的特性,称作“Round-robin dispatching”,消息会平均的发送给每一个消费者

你可能感兴趣的:(RabbitMq)