Work Queue 的模式
1.图解
2.其实第二种模式跟第一种模式是比较相似的,只是有两个或者多个消费者同时去消费一个队列。模式是采用平均份分配的方式。话不多说,上代码
3.消息提供者类
import com.example.amqp.demo.utils.RabbitMQUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import java.io.IOException;
public class Provider
{
public static void main(String[] args) throws IOException {
// 1.获取连接对象
Connection connection = RabbitMQUtils.getConnection();
// 2.获取通道对象
Channel channel = connection.createChannel();
// 3.通道绑定队列
channel.queueDeclare("work",true,false,false,null);
// 4.生产消息
for (int i = 0; i < 10; i++)
{
channel.basicPublish("","work",null,(i + "hello work queue").getBytes());
}
// 5.关闭资源
RabbitMQUtils.closeConnectionAndChanel(channel,connection);
}
}
4.消费者1
package com.example.amqp.demo.workQueue;
import com.example.amqp.demo.utils.RabbitMQUtils;
import com.rabbitmq.client.*;
import java.io.IOException;
public class Customer1
{
public static void main(String[] args) throws IOException
{
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));
}
});
}
}
5.消费者2
package com.example.amqp.demo.workQueue;
import com.example.amqp.demo.utils.RabbitMQUtils;
import com.rabbitmq.client.*;
import java.io.IOException;
public class Customer2
{
public static void main(String[] args) throws IOException
{
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));
}
});
}
}
运行结果截图
这种轮询的模式会有资源浪费的缺点。我们希望的是能者多劳,处理的快的消费者线程可以处理更多的消息。
我们需要做三步操作:
1.设置消费者每次只能消费一个消息
channel.basicQos(1); // 设置消费者每次只能消费一个消息
2.消息的自动确认机制设置为false
channel.basicConsume("work",false,new DefaultConsumer(channel){
3.处理完消息之后手动进行确认
// 手动确认 参数一:手动确认消息标志 参数二:false 每次确认一个
channel.basicAck(envelope.getDeliveryTag(),false);
运行结果: