首先从最基础的代码开始,我们通过RabbitMQ做一个简单的生产者,消费者模型
一,创建一个maven项目 pom.xml 引入依赖(需要你提前把RabbitMQ服务器配好,百度搜索一大堆这里不介绍了)
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>3.6.5</version>
</dependency>
二.创建一个RabbitMQ连接工厂工具类MQConnectionUtils
package com.jxd.util;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class MQConnectionUtils {
//创建新的MQ连接
public static Connection newConnection(){
//1.创建链接工厂
ConnectionFactory factoryMQ = new ConnectionFactory();
//2.设置链接地址
factoryMQ.setHost("127.0.0.1");
//3.设置用户名称
factoryMQ.setUsername("jxd");
//4.设置用户密码
factoryMQ.setPassword("123456");
//5.设置amqp协议端口号
factoryMQ.setPort(5672);//在Overview里边有amqp的协议端口号
//6.设置VirtualHost地址
factoryMQ.setVirtualHost("/jxd_host");//一定加上/
Connection newConnection = null;
try {
newConnection = factoryMQ.newConnection();//不用单例模式因为随时调用
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
return newConnection;
}
}
三,创建一个消息的生成者类
package com.jxd.util;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class Producer {
//队列名称
public static final String QUEUE_NAME ="jxd_123456";
public static void main(String[] args) {
//创建一个新的链接
Connection connection = MQConnectionUtils.newConnection();
//创建通道
try {
Channel channel=connection.createChannel();
//创建一个队列
channel.queueDeclare(QUEUE_NAME,false,false,false,null);
//创建消息
channel.basicQos(1);//表示队列给消费者发消息处,只能取一个,消费完毕才能取下一个当然也可以设多个
for(int i=0;i<50;i++){//连发送50个消息给消费者
String msg="hello world!!!"+i;
System.out.println("生产者投递消息内容: "+msg);
//生产者发送消息
channel.basicPublish("",QUEUE_NAME,null,msg.getBytes());
}
//关闭通道和连接
try {
channel.close();
} catch (TimeoutException e) {
e.printStackTrace();
}
connection.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
四,创建一个消费者
package com.jxd.util;
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class Consumer {
//队列名称
public static final String QUEUE_NAME ="jxd_123456";
public static void main(String[] args) {
System.out.println("消费者1");
//创建一个新的链接
Connection connection = MQConnectionUtils.newConnection();
//创建通道
try {
final Channel channel=connection.createChannel();
//消费者关联一个队列
channel.queueDeclare(QUEUE_NAME,false,false,false,null);//里边的这些fasle ,null 先不管一步步的来
channel.basicQos(1);
//监听获取消息
DefaultConsumer defaultConsumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope,
AMQP.BasicProperties properties, byte[] body) throws IOException{
String msg = new String(body,"UTF-8");
System.out.println("消费者获取生产者消息:"+msg);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
channel.basicAck(envelope.getDeliveryTag(),false);//false表示手动应答模式告诉队列已经处理成功
}
}
};
//设置应答模式
channel.basicConsume(QUEUE_NAME,false,defaultConsumer);//第二个参数true表示自动应答模式
} catch (IOException e) {
e.printStackTrace();
}
//消费者不能关闭要监听生产者发消息
}
}
到这里就完成了,代码可以复制粘贴拿过去直接跑,跑一下就知道了,放到main方法里边 启动就可以
这里顺便说一下,channel.basicQos(1);这个方法在生产者和消费者里边都有配置,比如我们这里有2个消费者同时监听一个生产者
但是消费者1运行速度快,而消费者2运行速度满,如果用自动应答模式channel.basicAck(envelope.getDeliveryTag(),true);//改为true为自动应答模式,系统会默认轮询操作,就是我不管谁快谁慢,都是1,2,1,2,1,2平均分配. 如果我们改为手动应答模式且channel.basicQos(1)这样就会是,当速度快的消费者完成之后,他会立马拿下一个消息进行处理,处理完之后在拿,就是能者多捞的意思.
注:以上代码如果做消费者集群,消费者代码你在复制粘贴一下(队列名称一样),在启动一个main方法就可以,然后你在消费1做一个Thred.sleep(500)表示比另一个消费者运行速度慢.这样就能测试到能者多劳的生产者消费者模型了.