Java简单实现MQ架构和思路01
实现一个 MQ(消息队列)架构可以涉及到很多方面,包括消息的生产和消费、消息的存储和传输、消息的格式和协议等等。下面是一个简单的 MQ 架构的实现示例,仅供参考:
- 定义消息格式和协议:我们可以定义一个简单的消息格式,比如 JSON 格式,包含消息的 ID、内容、发送时间等信息。同时,我们可以定义一个简单的协议,比如 TCP 协议,用来传输消息。 
- 实现消息的存储:我们可以使用数据库或者文件系统等方式来存储消息。对于消息队列来说,可以考虑使用类似于链表的数据结构来存储消息,每个节点包含一个消息和指向下一个节点的指针。 
- 实现消息的生产和消费:我们可以使用多线程来实现消息的生产和消费。具体地,我们可以定义一个生产者线程和多个消费者线程,生产者线程负责从外部系统中获取消息并存储到消息队列中,消费者线程负责从消息队列中获取消息并进行处理。 
- 实现消息的传输:我们可以使用 TCP 协议来传输消息。具体地,我们可以定义一个服务器程序,负责监听指定的端口号,并接受客户端的连接请求。一旦连接建立,服务器程序就可以和客户端进行数据传输。 
综上所述,一个简单的 MQ 架构的实现可以包含以上几个部分。实际上,MQ 的实现还涉及到很多其他方面,比如消息的确认和重试、消息的过期和删除、消息的优先级和分区等等。因此,在实际项目中,需要根据具体的需求和场景来进行设计和实现。
以下是一个简单的 Java 消息队列示例代码,使用了多线程和 TCP 协议:
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.LinkedList;
public class MessageQueue {
    private LinkedList<Message> queue = new LinkedList<Message>();
    public synchronized void putMessage(Message message) {
        queue.add(message);
        notifyAll();
    }
    public synchronized Message getMessage() throws InterruptedException {
        while (queue.isEmpty()) {
            wait();
        }
        return queue.removeFirst();
    }
    public static void main(String[] args) {
        MessageQueue queue = new MessageQueue();
        Producer producer = new Producer(queue);
        Consumer consumer1 = new Consumer(queue);
        Consumer consumer2 = new Consumer(queue);
        producer.start();
        consumer1.start();
        consumer2.start();
    }
}
class Message implements java.io.Serializable {
    private static final long serialVersionUID = 1L;
    private String id;
    private String content;
    public Message(String id, String content) {
        this.id = id;
        this.content = content;
    }
    public String getId() {
        return id;
    }
    public String getContent() {
        return content;
    }
}
class Producer extends Thread {
    private MessageQueue queue;
    public Producer(MessageQueue queue) {
        this.queue = queue;
    }
    public void run() {
        try {
            ServerSocket serverSocket = new ServerSocket(9999);
            while (true) {
                Socket socket = serverSocket.accept();
                ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
                Message message = (Message) ois.readObject();
                queue.putMessage(message);
                ois.close();
                socket.close();
            }
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
class Consumer extends Thread {
    private MessageQueue queue;
    public Consumer(MessageQueue queue) {
        this.queue = queue;
    }
    public void run() {
        try {
            while (true) {
                Message message = queue.getMessage();
                System.out.println("Consumer " + getId() + " got message: " + message.getContent());
                Socket socket = new Socket("localhost", 9998);
                ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
                oos.writeObject(message);
                oos.close();
                socket.close();
            }
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}
在这个示例中,我们定义了一个简单的消息队列,使用了一个链表来存储消息。然后,我们定义了一个生产者线程和两个消费者线程,生产者线程负责从外部系统中获取消息并存储到消息队列中,消费者线程负责从消息队列中获取消息并进行处理。我们使用 TCP 协议来传输消息,生产者线程监听端口号 9999,消费者线程通过连接 localhost 的 9998 端口来发送消息。在实际应用中,需要根据具体需求进行修改和扩展。
并在此代码基础上增加 协议类和注释
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.LinkedList;
// 消息队列类
public class MessageQueue {
    private LinkedList<Message> queue = new LinkedList<Message>();
    // 往队列中添加消息
    public synchronized void putMessage(Message message) {
        queue.add(message);
        notifyAll();
    }
    // 从队列中取出消息
    public synchronized Message getMessage() throws InterruptedException {
        while (queue.isEmpty()) {
            wait();
        }
        return queue.removeFirst();
    }
    // 主函数
    public static void main(String[] args) {
        MessageQueue queue = new MessageQueue();
        Producer producer = new Producer(queue);
        Consumer consumer1 = new Consumer(queue);
        Consumer consumer2 = new Consumer(queue);
        producer.start();
        consumer1.start();
        consumer2.start();
    }
}
// 消息类
class Message implements java.io.Serializable {
    private static final long serialVersionUID = 1L;
    private String type; // 消息类型,例如:ORDER, PAYMENT, SHIPMENT, 等等
    private String content; // 消息内容
    private String sender; // 消息发送者
    private String receiver; // 消息接收者
    // 构造方法
    public Message(String type, String content, String sender, String receiver) {
        super();
        this.type = type;
        this.content = content;
        this.sender = sender;
        this.receiver = receiver;
    }
    // 返回消息类型
    public String getType() {
        return type;
    }
    // 返回消息内容
    public String getContent() {
        return content;
    }
    // 返回消息发送者
    public String getSender() {
        return sender;
    }
    // 返回消息接收者
    public String getReceiver() {
        return receiver;
    }
}
// 编解码协议类
class Protocol {
    public static final String HEADER = "MESSAGE"; // 消息头
    public static final String DELIMITER = ":"; // 分隔符
    // 将消息编码为字符串
    public static String encode(Message message) {
        return HEADER + DELIMITER + message.getType() + DELIMITER + message.getContent() + DELIMITER
                + message.getSender() + DELIMITER + message.getReceiver();
    }
    // 将字符串解码为消息
    public static Message decode(String messageString) {
        String[] parts = messageString.split(DELIMITER);
        return new Message(parts[1], parts[2], parts[3], parts[4]);
    }
}
// 生产者线程类
class Producer extends Thread {
    private MessageQueue queue;
    private ServerSocket serverSocket;
    // 构造方法
    public Producer(MessageQueue queue) {
        this.queue = queue;
    }
    // 启动线程
    public void run() {
        try {
            serverSocket = new ServerSocket(9999); // 监听端口号9999
            while (true) {
                Socket socket = serverSocket.accept(); // 接收连接
                ObjectInputStream in = new ObjectInputStream(socket.getInputStream()); // 创建输入流
                String messageString = (String) in.readObject(); // 读取消息字符串
                Message message = Protocol.decode(messageString); // 解码消息
                queue.putMessage(message); // 添加消息到队列
                in.close(); // 关闭输入流
                socket.close(); // 关闭连接
            }
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
// 消费者线程类
class Consumer extends Thread {
    private MessageQueue queue;
    // 构造方法
    public Consumer(MessageQueue queue) {
        this.queue = queue;
    }
    // 启动线程
    public void run() {
        while (true) {
            try {
                Message message = queue.getMessage(); // 从队列中取出消息
                System.out.println("Received message: " + message.getContent()); // 输出消息内容
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
以下是在上面代码基础上增加消息确认和重试功能:
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.LinkedList;
// 消息队列类
public class MessageQueue {
    private LinkedList<Message> queue = new LinkedList<Message>();
    // 往队列中添加消息
    public synchronized void putMessage(Message message) {
        queue.add(message);
        notifyAll();
    }
    // 从队列中取出消息
    public synchronized Message getMessage() throws InterruptedException {
        while (queue.isEmpty()) {
            wait();
        }
        return queue.removeFirst();
    }
    // 主函数
    public static void main(String[] args) {
        MessageQueue queue = new MessageQueue();
        Producer producer = new Producer(queue);
        Consumer consumer1 = new Consumer(queue);
        Consumer consumer2 = new Consumer(queue);
        producer.start();
        consumer1.start();
        consumer2.start();
    }
}
// 消息类
class Message implements java.io.Serializable {
    private static final long serialVersionUID = 1L;
    private String type; // 消息类型,例如:ORDER, PAYMENT, SHIPMENT, 等等
    private String content; // 消息内容
    private String sender; // 消息发送者
    private String receiver; // 消息接收者
    private boolean confirmed; // 消息是否已确认
    private int retryCount; // 消息重试次数
    // 构造方法
    public Message(String type, String content, String sender, String receiver) {
        super();
        this.type = type;
        this.content = content;
        this.sender = sender;
        this.receiver = receiver;
        confirmed = false;
        retryCount = 0;
    }
    // 返回消息类型
    public String getType() {
        return type;
    }
    // 返回消息内容
    public String getContent() {
        return content;
    }
    // 返回消息发送者
    public String getSender() {
        return sender;
    }
    // 返回消息接收者
    public String getReceiver() {
        return receiver;
    }
    // 返回消息是否已确认
    public boolean isConfirmed() {
        return confirmed;
    }
    // 设置消息已确认
    public void setConfirmed() {
        confirmed = true;
    }
    // 返回消息重试次数
    public int getRetryCount() {
        return retryCount;
    }
    // 增加消息重试次数
    public void incrementRetryCount() {
        retryCount++;
    }
}
// 编解码协议类
class Protocol {
    public static final String HEADER = "MESSAGE"; // 消息头
    public static final String DELIMITER = ":"; // 分隔符
    // 将消息编码为字符串
    public static String encode(Message message) {
        return HEADER + DELIMITER + message.getType() + DELIMITER + message.getContent() + DELIMITER
                + message.getSender() + DELIMITER + message.getReceiver() + DELIMITER + message.isConfirmed()
                + DELIMITER + message.getRetryCount();
    }
    // 将字符串解码为消息
    public static Message decode(String messageString) {
        String[] parts = messageString.split(DELIMITER);
        Message message = new Message(parts[1], parts[2], parts[3], parts[4]);
        message.setConfirmed(Boolean.parseBoolean(parts[5]));
        message.incrementRetryCount();
        return message;
    }
}
// 生产者线程类
class Producer extends Thread {
    private MessageQueue queue;
    private ServerSocket serverSocket;
    // 构造方法
    public Producer(MessageQueue queue) {
        this.queue = queue;
    }
   // 启动线程
    public void run() {
        try {
            serverSocket = new ServerSocket(9999); // 监听端口号9999
            while (true) {
                Socket socket = serverSocket.accept(); // 接收连接
                ObjectInputStream in = new ObjectInputStream(socket.getInputStream()); // 创建输入流
                ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream()); // 创建输出流
                String messageString = (String) in.readObject(); // 读取消息字符串
                Message message = Protocol.decode(messageString); // 解码为消息对象
                if (!message.isConfirmed()) { // 如果消息未确认
                    queue.putMessage(message); // 添加到队列中
                }
                out.writeObject("ACK"); // 发送确认消息
                out.flush();
                in.close();
                out.close();
                socket.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace
        }
    }
}Java简单实现MQ架构和思路01的更多相关文章
- 为什么要用消息队列 及 自己如何设计一个mq架构
		1. 解耦:如左图, 系统a因为业务需求需要调用系统b,后续因为业务需求可能需要改代码调用系统c,甚至还要考虑被调用的系统挂了访问超时的问题.耦合性太高! 如右图, 系统a产生一条数据发送到消息队列里 ... 
- 手把手教你用redis实现一个简单的mq消息队列(java)
		众所周知,消息队列是应用系统中重要的组件,主要解决应用解耦,异步消息,流量削锋等问题,实现高性能,高可用,可伸缩和最终一致性架构.目前使用较多的消息队列有 ActiveMQ,RabbitMQ,Zero ... 
- 整理下.net分布式系统架构的思路
		最近看到有部分招聘信息,要求应聘者说一下分布式系统架构的思路.今天早晨正好有些时间,我也把我们实际在.net方面网站架构的演化路线整理一下,只是我自己的一些想法,欢迎大家批评指正. 首先说明的是.ne ... 
- 高吞吐高并发Java NIO服务的架构(NIO架构及应用之一)
		高吞吐高并发Java NIO服务的架构(NIO架构及应用之一) http://maoyidao.iteye.com/blog/1149015 Java NIO成功的应用在了各种分布式.即时通信和中 ... 
- Java生鲜电商平台-Java后端生成Token架构与设计详解
		Java生鲜电商平台-Java后端生成Token架构与设计详解 目的:Java开源生鲜电商平台-Java后端生成Token目的是为了用于校验客户端,防止重复提交. 技术选型:用开源的JWT架构. 1. ... 
- java简单数据类型转化
		java简单数据类型,有低级到高级为:(byte,short,char)→int→long→float→double (boolean不参与运算转化) 转化可以分为 低级到高级的自动转化 高级到低级的 ... 
- 00:Java简单了解
		浅谈Java之概述 Java是SUN(Stanford University Network),斯坦福大学网络公司)1995年推出的一门高级编程语言.Java是一种面向Internet的编程语言.随着 ... 
- java简单学生成绩管理系统
		题目要求: 一. 数据结构要求:(5 分) 1.定义 ScoreInformation 类,其中包括七个私有变量(stunumber, name, mathematicsscore, englishi ... 
- MVC架构模式分析与设计(一)---简单的mvc架构
		首先 我要感谢慕课网的老师提供视频资料 http://www.imooc.com/learn/69 下面我来进行笔记 我们制作一个简单的mvc架构 制作第一个控制器 testController.cl ... 
- java简单词法分析器(源码下载)
		java简单词法分析器 : http://files.cnblogs.com/files/hujunzheng/%E7%AE%80%E5%8D%95%E8%AF%8D%E6%B3%95%E5%88%8 ... 
随机推荐
- OpenHarmony 3.2 Beta1版本正式发布
			5 月 31 日,开放原子开源基金会正式发布 OpenAtom OpenHarmony(以下简称"OpenHarmony")3.2 Beta1 版本. 全球开发者可通过Gite ... 
- [一本通1681]统计方案 题解(Meet in mid与逆元的结合)
			题目描述 小\(B\)写了一个程序,随机生成了\(n\)个正整数,分别是\(a[1]-a[n]\),他取出了其中一些数,并把它们乘起来之后模\(p\),得到了余数\(c\).但是没过多久,小\(B\) ... 
- C# 循环与条件语句详解
			C# Switch 语句 使用 switch 语句选择要执行的多个代码块中的一个. 示例: switch(expression) { case x: // 代码块 break; case y: // ... 
- Windows wsl2安装Ubuntu
			wsl(Windows Subsystem for Linux)即适用于Windows的Linux子系统,是一个实现在Windows 10 / 11上运行原生Linux的技术. wsl2 为其迭代版本 ... 
- HarmonyOS音频通话开发指导
			常用的音频通话模式包括VOIP通话和蜂窝通话. ● VOIP通话:VOIP(Voice over Internet Protocol)通话是指基于互联网协议(IP)进行通讯的一种语音通话技术.VO ... 
- 第十篇:异步IO、消息队列
			一.协程 二.异步IO_Gevent 三.协程异步IO操作 四.事件驱动模型 五.IO多路复用 六.异步IO理论 一.回顾 线程 vs 进程 线程:CPU最小调度单位,内存共享: 线程同时修改同一份数 ... 
- 重新整理数据结构与算法(c#)——算法套马踏棋算法[三十三]
			前言 马踏棋盘 概念在这,不做过多复述. https://baike.sogou.com/v58959803.htm?fromTitle=马踏棋盘 思路是这样子的,一匹马有上面几种做法,然后进行尝试, ... 
- Redis为什么是单线程还支持高并发
			Redis为什么设计成单线程模式因为redis是基于内存的读写操作,所以CPU不是性能瓶颈,而单线程更好实现,所以就设计成单线程模式 单线程模式省却了CPU上下文切换带来的开销问题,也不用去考虑各种锁 ... 
- 力扣278(java&python)-第一个错误的版本(简单)
			题目: 你是产品经理,目前正在带领一个团队开发新的产品.不幸的是,你的产品的最新版本没有通过质量检测.由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的. 假设你有 n 个版本 ... 
- HarmonyOS NEXT应用开发—在Native侧实现进度通知功能
			介绍 本示例通过模拟下载场景介绍如何将Native的进度信息实时同步到ArkTS侧. 效果图预览 使用说明 点击"Start Download"按钮后,Native侧启动子线程模拟 ... 
