消息队列的功能
消息队列,它包含了两个关键词:消息和队列。
1,消息是指在应用间传输的数据,消息队列的表现形式是多样的(文本,结构化的对象格式)
2,对于队列,抽象意义上来说,就是消息的进和出,从时间意义上来说进和出不一定是同步
的,因此一个典型的消息队列,至少要包含消息的发送、接收和暂存功能(如图)
1. 消息处理中心:负责消息的接受、存储、转发等
2. 消息生产者:负责产生和发送消息到消息处理中心
3. 消息消费者:负责从消息处理中心获取消息,并进行相应的处理
设计一个简单的消息队列
从上面我们可以得到结论,消息队列服务的核心是消息处理中心,它至少要具备消息发送、
消息接收的消息暂存的功能。
消息处理中心
import java.util.concurrent.ArrayBlockingQueue;
/**
* 消息处理中心
*/
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){
/*
offer()--- 如果插入数据时队列没满 返回true 如果满了返回false
*/
if (messageQueue.offer(msg)){
System.out.println("成功向消息队列中投递信息:"+msg+"当前暂存消息队列的数量是"+messageQueue.size());
}else {
System.out.println("消息处理中心暂存的消息达到最大负荷,不能继续放入消息");
}
System.out.println("------------------------------------");
}
//消费消息
public static String consume(){
/*
pool方法删除数据时队列不为null 则返回队列头部的数据 如果队列为null立即返回null
*/
String msg=messageQueue.poll();
if (msg!=null){
System.out.println("已经消费消息:"+msg+",当前暂存的消息数量是:"+messageQueue.size());
}else {
System.out.println("消息队列中已经没有消息可供消费!");
}
System.out.println("------------------------------------");
return msg;
}
}
外提供Broker类服务
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
/**
* BrokerServer 类来对外提供Broker类服务
*/
public class BrokerServer implements Runnable{
public static int serverPort= 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);
if (str.equals("CONSUME")){//CONSUME 表示要消费一条信息
String message = Broker.consume();
out.println(message);
out.flush();
}
else{
Broker.produce(str);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(serverPort);
while (true){
//-----accept 该方法如无连接会阻塞等待连接
BrokerServer brokerServer = new BrokerServer(serverSocket.accept());
new Thread(brokerServer).start();
}
}
}
客户端访问
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
/**
* 客户端访问
*/
public class MqClient {
//生产消息
public static void produce(String message) throws Exception{
Socket socket = new Socket(InetAddress.getLocalHost(),BrokerServer.serverPort);
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.serverPort);
try (
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream());
){
//先向消息队列发发送字符串表示消费
out.println("CONSUME");
out.flush();
//在从消息队列中获取一条消息
String message = in.readLine();
return message;
}
}
}
测试生产消息(向服务中心队列添加数据)
public class ProduceCLient {
public static void main(String[] args) throws Exception{
MqClient.produce("hello World");
}
}
测试消费消息(向服务中心队列删除数据)
public class ConsumeClient {
public static void main(String[] args) throws Exception{
String message = MqClient.consume();
System.out.println("获取的消息为:"+message);
}
}
测试结果如下
接收到原始数据:hello World
成功向消息队列中投递信息:hello World当前暂存消息队列的数量是1
------------------------------------
接收到原始数据:hello World
成功向消息队列中投递信息:hello World当前暂存消息队列的数量是2
------------------------------------
接收到原始数据:hello World
成功向消息队列中投递信息:hello World当前暂存消息队列的数量是3
------------------------------------
接收到原始数据:hello World
消息处理中心暂存的消息达到最大负荷,不能继续放入消息
------------------------------------
接收到原始数据:hello World
消息处理中心暂存的消息达到最大负荷,不能继续放入消息
------------------------------------
接收到原始数据:CONSUME
已经消费消息:hello World,当前暂存的消息数量是:2
------------------------------------
接收到原始数据:CONSUME
已经消费消息:hello World,当前暂存的消息数量是:1
------------------------------------
接收到原始数据:CONSUME
已经消费消息:hello World,当前暂存的消息数量是:0
------------------------------------
Process finished with exit code 130 (interrupted by signal 2: SIGINT)