一、HelloWord模型
一个生产者绑定一个消息队列对应一个消费者的简单模型。如图所示:
二、创建RabbitMq连接
先搞一个 RabbitMqUtil.getConnection()方法,通过RabbitMq 的 ConnectionFactory工厂类,创建一个消息连接后返回该连接:
package hello;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* @Description:
* @Date: 2020/6/15
* @Author: DongYiFan
*/
public class RabbitMQUtil {
/**
* 自定义连接工具
* @param rHost rabbit主机Host
* @param rPort rabbit主机端口
* @param vHost rabbit虚拟主机Host
* @param usr 用户名
* @param pwd 用户密码
* @return
* @throws IOException
* @throws TimeoutException
*/
public static Connection getConnection(String rHost, int rPort,
String vHost, String usr, String pwd) throws IOException, TimeoutException {
//创建连接工程
ConnectionFactory factory = new ConnectionFactory();
factory.setHost(rHost);
factory.setPort(rPort);
factory.setVirtualHost(vHost);
factory.setUsername(usr);
factory.setPassword(pwd);
System.out.println(rHost+","+rPort+","+vHost+","+usr+","+pwd);
Connection c = factory.newConnection();
return c;
}
}
二、创建生产者线程
生存者线程不需要一直保持运行,生存者将信息存入消息队列后,可以关闭当前RabbitMq连接。
package hello;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* @Description:
* @Date: 2020/6/15
* @Author: DongYiFan
*/
public class ProviderThread implements Runnable {
@Override
public void run() {
Connection connection = null;
Channel channel = null;
try {
connection = RabbitMQUtil.getConnection("127.0.0.1", 5672, "/", "root", "root");
channel = connection.createChannel();
//绑定通道和对应的消息队列
/**
* 参数1:Queue名称, 没有时创建
* 参数2:是否持久化
* 参数3:是否独占队列(对于当前链接而言)
* 参数4:是否在消费完成后自动删除队列
* 参数5:额外的附加参数
*/
channel.queueDeclare("hello", false, false, false, null);
//发布消息
/**
* 参数1:交换机名称, 不适用交换机为空串儿
* 参数2:通道名称
* 参数3:其他设置
* 参数4:传递的消息内容,byte[]
*/
channel.basicPublish("","hello",null,"hello".getBytes());
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}finally {
if (channel != null) {
try {
channel.close();
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
三、消费者线程
消费者随时监听消息队列,消费者线程应一直运行,当关闭消费者持有得连接时,消费者线程会被关闭,不能继续调用消费回调函数。
package hello;
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* @Description:
* @Date: 2020/6/16
* @Author: DongYiFan
*/
public class CustomerThread implements Runnable {
private int i = 0;
@Override
public void run() {
Connection connection = null;
Channel channel = null;
try {
connection = RabbitMQUtil.getConnection("127.0.0.1", 5672,"/","root","root");
//绑定通道和对应的消息队列
/**
* 参数1:Queue名称, 没有时创建
* 参数2:是否持久化
* 参数3:是否独占队列(对于当前链接而言)
* 参数4:是否在消费完成后自动删除队列
* 参数5:额外的附加参数
*/
channel = connection.createChannel();
channel.queueDeclare("hello",false,false,false,null);
/**
* 基础消费方法
* 参数1:选择消息队列
* 参数2:是否开启消息自动确认机制
* 参数3:消费消息时的回调接口(重写DefaultConsumer接口)
* 消息消费者会持续得监听消费队列, 该线程应该持续进行,当连接关闭时,该线程会被关闭
*/
channel.basicConsume("hello", true, new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
super.handleDelivery(consumerTag, envelope, properties, body);
System.out.println(new String(body)+"i:"+i++);
}
});
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
}
}
四运行及效果
模拟了50个线程先生产50条消息,开启消费者线程后,这50条消息会被消费掉,消费者线程处于监听等待状态。等待1000ms后,一个新的生产者生成了一条新消息,然后该消费者立刻消费了该条消息。
public static void main(String[] args) throws InterruptedException {
ProviderThread pt = new ProviderThread();
for (int i=0; i<50 ;i++){
Thread thread = new Thread(pt);
Thread.sleep(20);
thread.start();
}
Thread.sleep(3000);
CustomerThread ct = new CustomerThread();
new Thread(ct).start();
Thread.sleep(1000);
Thread thread = new Thread(pt);
thread.start();
}