第一章 消息队列
1 设计一个简单的消息队列
消息队列的完整使用场景至少包含三个角色:
消息处理中心 | 负责消息的接收、存储、转发等 |
---|---|
消息生产者 | 负责产生和发送消息到消息处理中心 |
消息消费者 | 负责从消息处理中心获取消息,并进行相应的处理 |
1.1 消息处理中心
package cn.distributed.msg;
import java.util.concurrent.ArrayBlockingQueue;
/**
* ClassName:Broker
* Description:消息处理中心
* Author:tanglp
* Date:2022/9/13
*/
public class Broker {
// 存储消息最大数量
private final static int MAX_SIZE = 3;
// 保存消息数据的容器
private static ArrayBlockingQueue<String> messageQueue = new ArrayBlockingQueue(MAX_SIZE);
// 生产消息
public static void produce(String msg) {
if (messageQueue.offer(msg)) {
System.out.println("成功向消息处理中心投递消息:" + msg + ",当前暂存消息数量是:" + messageQueue.size());
}else {
System.out.println("消息处理中心内暂存的消息达到最大负荷,不能继续放入消息!");
}
}
// 消费消息
public static String consume() {
String msg = messageQueue.poll();
if (msg != null) {
// 消息条件满足情况,从消息容器中取出一条消息
System.out.println("已经消费消息:" + msg + ",当前暂存消息数量是:" + messageQueue.size());
}else {
System.out.println("消息处理中心内没有消息可提供消费!");
}
return msg;
}
}
1.2 对Broker提供服务
package cn.distributed.msg;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
/**
* ClassName:BrokerServer
* Description:消息服务提供
* Author:tanglp
* Date:2022/9/13
*/
public class BrokerServer implements Runnable {
public static int SERVICE_PORT = 9999;
private final Socket socket;
public BrokerServer(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try(BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream())) {
while (true) {
String str = in.readLine();
if (str == null) {
continue;
}
System.out.println("接收到原始数据:" + str);
// CONSUME表示要消费一条消息
if (str.equals("CONSUME")) {
// 从消息队列中消费一条消息
String message = Broker.consume();
out.println(message);
out.flush();
}else {
// 其他情况都表示生产消息放到消息队列中
Broker.produce(str);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
ServerSocket server = new ServerSocket(SERVICE_PORT);
while (true) {
BrokerServer brokerServer = new BrokerServer(server.accept());
new Thread(brokerServer).start();
}
}
}
1.3 客户端访问
package cn.distributed.msg;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
/**
* ClassName:MqClient
* Description:客户端访问
* Author:tanglp
* Date:2022/9/13
*/
public class MqClient {
// 生产消息
public static void produce(String message) throws Exception {
Socket socket = new Socket(InetAddress.getLocalHost(), BrokerServer.SERVICE_PORT);
try(PrintWriter out = new PrintWriter(socket.getOutputStream())) {
out.println(message);
out.flush();
}
}
// 消费消息
public static String consume() throws Exception {
Socket socket = new Socket(InetAddress.getLocalHost(), BrokerServer.SERVICE_PORT);
try(BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream())) {
// 先向消息队列中发送字符串"CONSUME"表示消费
out.println("CONSUME");
out.flush();
// 再从消息队列获取一条消息
String message = in.readLine();
return message;
}
}
}
1.4 实现
package cn.distributed.msg;
/**
* ClassName:Main
* Description:
* Author:tanglp
* Date:2022/9/13
*/
public class Main {
}
class ProduceClient {
public static void main(String[] args) throws Exception {
MqClient client = new MqClient();
client.produce("hello world");
}
}
class ConsumeClient {
public static void main(String[] args) throws Exception {
MqClient client = new MqClient();
String consume = client.consume();
System.out.println("获取到的消息为:" + consume);
}
}
1.5 结果展示: