工作队列:也被称作为任务队列,让多个消费者绑定到一个队列,共同消费队列中的消息,队列中的消息一旦被消费,就会消失,因此任务是不会被重复执行的。
在上图模型中,有以下概念:
P:生产者,任务的发布者
C1:消费者1,领取任务并完成任务
C2:消费者2,领取任务并完成任务
代码实现:
1.创建生产者
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import utils.RabbitMQUtils;
import java.io.IOException;
/**
* 生产者
*/
public class Provider {
public static void main(String[] args) throws IOException {
//获取连接对象
Connection connection = RabbitMQUtils.getConnection();
//获取通道对象
Channel channel = connection.createChannel();
//通过通道声明队列
channel.queueDeclare("work",true,false,false,null);
//生产消息
for (int i = 0; i <10 ; i++) {
channel.basicPublish("","work",null,(i+"hello work queue").getBytes());
}
//关闭资源
RabbitMQUtils.closeConnectionAndChanel(channel,connection);
}
}
2.创建消费者1
import com.rabbitmq.client.*;
import utils.RabbitMQUtils;
import java.io.IOException;
/**
* 消费者1
*/
public class Customer1 {
public static void main(String[] args) throws Exception {
//获取连接对象
Connection connection = RabbitMQUtils.getConnection();
//获取通道对象
Channel channel = connection.createChannel();
channel.queueDeclare("work",true,false,false,null);
channel.basicConsume("work",true,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("消费者1:"+new String(body));
}
});
}
}
3.创建消费者2
import com.rabbitmq.client.*;
import utils.RabbitMQUtils;
import java.io.IOException;
/**
* 消费者2
*/
public class Customer2 {
public static void main(String[] args) throws Exception {
//获取连接对象
Connection connection = RabbitMQUtils.getConnection();
//获取通道对象
Channel channel = connection.createChannel();
channel.queueDeclare("work",true,false,false,null);
channel.basicConsume("work",true,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("消费者2:"+new String(body));
}
});
}
}
4.分别启动消费者1和消费者2
5.然后启动生产者即可看到消费者1和消费者2消费消息
发现消费的消息数量是一致的,官网对这个有说明
翻译过来是:默认情况下,RabbitMQ 将按顺序将每条消息发送给下一个消费者。平均每个消费者都会收到相同数量的信息。这种分发消息的方式称为循环
平均分配会产生一个问题,就是当有消费者消费消息过慢时,其他消费者已经闲置了,没有实现“能者多劳”
我们希望能力强的多处理一些,慢的少处理一些。之所以会平均分配,是因为rabbitmq的消息自动确认机制。
实现能者多劳:
修改消费者中的代码
1.自动确认置为 false
2.在消费者中添加代码 channel.basicQos(1);
3.添加代码 channel.basicAck(envelope.getDeliveryTag(),false);
同时修改消费者1和消费者2中的代码
import com.rabbitmq.client.*;
import utils.RabbitMQUtils;
import java.io.IOException;
/**
* 消费者2
*/
public class Customer2 {
public static void main(String[] args) throws Exception {
//获取连接对象
Connection connection = RabbitMQUtils.getConnection();
//获取通道对象
Channel channel = connection.createChannel();
//每次只能消费一个消息
channel.basicQos(1);
channel.queueDeclare("work",true,false,false,null);
channel.basicConsume("work",false,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("消费者2:"+new String(body));
//参数1:确认队列中那个具体消息
//参数2:是否开启多个消息同时确认
channel.basicAck(envelope.getDeliveryTag(),false);
}
});
}
}
import com.rabbitmq.client.*;
import utils.RabbitMQUtils;
import java.io.IOException;
/**
* 消费者1
*/
public class Customer1 {
public static void main(String[] args) throws Exception {
//获取连接对象
Connection connection = RabbitMQUtils.getConnection();
//获取通道对象
Channel channel = connection.createChannel();
//每次只能消费一个消息
channel.basicQos(1);
channel.queueDeclare("work",true,false,false,null);
channel.basicConsume("work",false,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("消费者1:"+new String(body));
//参数1:确认队列中那个具体消息
//参数2:是否开启多个消息同时确认
channel.basicAck(envelope.getDeliveryTag(),false);
}
});
}
}
更多:
RabbitMQ学习笔记一:了解及在Linux下安装RabbitMQ