Java 开发 - 简单消息队列实现、主题消息队列实现

简单消息队列

1、MessageQueue
  • SimpleMessageQueue.java
java 复制代码
public class SimpleMessageQueue<T> {

    private final BlockingQueue<T> queue;
    private final ExecutorService executor = Executors.newCachedThreadPool();
    private volatile boolean running = true;

    public SimpleMessageQueue(int capacity) {
        this.queue = new ArrayBlockingQueue<>(capacity);
    }

    // 获取队列大小
    public int size() {
        return queue.size();
    }

    // 停止队列
    public void stop() {
        running = false;
        executor.shutdownNow();
    }

    // 发送消息
    public boolean send(T message) {
        return queue.offer(message);
    }

    // 发送消息,如果队列已满,则阻塞
    public void sendBlocking(T message) throws InterruptedException {
        queue.put(message);
    }

    // 消费消息
    public void consume(Consumer<T> consumer) {
        executor.submit(() -> {
            while (running && !Thread.currentThread().isInterrupted()) {
                try {
                    T message = queue.take();
                    consumer.accept(message);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    Thread.currentThread().interrupt();
                }
            }
        });
    }
}
2、Test
java 复制代码
SimpleMessageQueue<String> simpleMessageQueue = new SimpleMessageQueue<>(10);

// 消费者
simpleMessageQueue.consume(message -> {
    System.out.println("consumer receive: " + message);

    // 模拟消费时间
    try {
        Thread.sleep(2 * 1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
});

// 生产者
for (int i = 0; i < 5; i++) {

    // 模拟生产时间
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    try {
        String message = "message" + (i + 1);
        simpleMessageQueue.sendBlocking(message);
        System.out.println("producer send: " + message);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
复制代码
# 输出结果

producer send: message1
consumer receive: message1
producer send: message2
consumer receive: message2
producer send: message3
producer send: message4
consumer receive: message3
producer send: message5
consumer receive: message4
consumer receive: message5
java 复制代码
SimpleMessageQueue<String> simpleMessageQueue = new SimpleMessageQueue<>(10);

for (int i = 0; i < 5; i++) {
    String producerId = "producer" + (i + 1);
    new Thread(() -> {

        // 生产者
        for (int j = 0; j < 3; j++) {

            // 模拟生产时间
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            try {
                String message = producerId + " - message" + (j + 1);
                simpleMessageQueue.sendBlocking(message);
                System.out.println(producerId + " send: " + message);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }).start();
}

// 消费者
simpleMessageQueue.consume(message -> {
    System.out.println("consumer receive: " + message);

    // 模拟消费时间
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
});
复制代码
# 输出结果

producer2 send: producer2 - message1
producer5 send: producer5 - message1
producer4 send: producer4 - message1
producer3 send: producer3 - message1
consumer receive: producer5 - message1
producer1 send: producer1 - message1
producer5 send: producer5 - message2
producer4 send: producer4 - message2
producer2 send: producer2 - message2
producer3 send: producer3 - message2
producer1 send: producer1 - message2
consumer receive: producer3 - message1
producer5 send: producer5 - message3
producer4 send: producer4 - message3
consumer receive: producer4 - message1
producer2 send: producer2 - message3
consumer receive: producer2 - message1
producer1 send: producer1 - message3
consumer receive: producer1 - message1
producer3 send: producer3 - message3
consumer receive: producer5 - message2
consumer receive: producer4 - message2
consumer receive: producer2 - message2
consumer receive: producer3 - message2
consumer receive: producer1 - message2
consumer receive: producer5 - message3
consumer receive: producer4 - message3
consumer receive: producer2 - message3
consumer receive: producer1 - message3
consumer receive: producer3 - message3

主题消息队列

1、MessageQueue
  • TopicMessageQueue.java
java 复制代码
public class TopicMessageQueue<T> {

    private final Map<String, Map<Consumer<T>, BlockingQueue<T>>> topicMap = new ConcurrentHashMap<>();
    private final ExecutorService executor = Executors.newCachedThreadPool();
    private final int queueCapacity;

    public TopicMessageQueue(int queueCapacity) {
        this.queueCapacity = queueCapacity;
    }

    public void stop() {
        executor.shutdownNow();
    }

    // 发布消息到主题
    public void publish(String topic, T message) {
        Map<Consumer<T>, BlockingQueue<T>> queueMap = topicMap.get(topic);
        if (queueMap == null) {
            return;
        }
        for (BlockingQueue<T> queue : queueMap.values()) {
            queue.offer(message);
        }
    }

    // 订阅主题
    // 允许一个消费者订阅多个主题
    // 不允许一个消费者订阅重复订阅同一个主题
    public void subscribe(String topic, Consumer<T> consumer) {
        Map<Consumer<T>, BlockingQueue<T>> queueMap = topicMap.get(topic);

        if (queueMap == null) {

            // 如果 queueMap 为 null,说明还没有任何消费者订阅该主题
            // 不需要检查当前消费者是否已经订阅了该主题

            queueMap = new ConcurrentHashMap<>();
            topicMap.put(topic, queueMap);
        } else {

            // 如果 queueMap 不为 null,说明已经有消费者订阅了该主题
            // 需要检查当前消费者是否已经订阅了该主题

            if (queueMap.containsKey(consumer)) {
                return;
            }
        }

        BlockingQueue<T> queue = new LinkedBlockingQueue<>(queueCapacity);
        queueMap.put(consumer, queue);

        executor.submit(() -> {
            while (!Thread.currentThread().isInterrupted()) {
                try {
                    T message = queue.take();
                    consumer.accept(message);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    break;
                }
            }
        });
    }

    // 取消订阅主题
    public void unsubscribe(String topic, Consumer<T> consumer) {
        Map<Consumer<T>, BlockingQueue<T>> queueMap = topicMap.get(topic);
        if (queueMap == null) {
            return;
        }
        queueMap.remove(consumer);
    }
}
2、Test
java 复制代码
TopicMessageQueue<String> topicMessageQueue = new TopicMessageQueue<>(10);

// 消费者
Consumer<String> consumer1 = message -> System.out.println("consumer1 收到消息: " + message);
Consumer<String> consumer2 = message -> System.out.println("consumer2 收到消息: " + message);
Consumer<String> consumer3 = message -> System.out.println("consumer3 收到消息: " + message);

// 订阅主题
topicMessageQueue.subscribe("sports", consumer1);
topicMessageQueue.subscribe("sports", consumer2);
topicMessageQueue.subscribe("news", consumer3);
topicMessageQueue.subscribe("news", consumer1);

// 发布消息
topicMessageQueue.publish("sports", "篮球比赛开始");
topicMessageQueue.publish("news", "今日头条新闻");
topicMessageQueue.publish("sports", "足球比赛结果");

try {
    Thread.sleep(1000);
} catch (InterruptedException e) {
    e.printStackTrace();
}

// 取消订阅
topicMessageQueue.unsubscribe("sports", consumer1);

topicMessageQueue.publish("sports", "这条消息只有 consumer2 能收到");

try {
    Thread.sleep(1000);
} catch (InterruptedException e) {
    e.printStackTrace();
}

topicMessageQueue.stop();
复制代码
# 输出结果

consumer3 收到消息: 今日头条新闻
consumer1 收到消息: 篮球比赛开始
consumer2 收到消息: 篮球比赛开始
consumer1 收到消息: 今日头条新闻
consumer2 收到消息: 足球比赛结果
consumer1 收到消息: 足球比赛结果
consumer2 收到消息: 这条消息只有 consumer2 能收到
相关推荐
代码旅人ing9 分钟前
链表算法刷题指南
数据结构·算法·链表
2401_8274999912 分钟前
python项目实战09-AI智能伴侣(ai_partner_5-6)
开发语言·python
PD我是你的真爱粉14 分钟前
MCP 协议详解:从架构、工作流到 Python 技术栈落地
开发语言·python·架构
Yungoal14 分钟前
常见 时间复杂度计算
c++·算法
win x35 分钟前
Redis 使用~如何在Java中连接使用redis
java·数据库·redis
星晨雪海41 分钟前
基于 @Resource 的支付 Service 多实现类完整示例
java·开发语言
阿维的博客日记1 小时前
什么是逃逸分析
java·juc
ACP广源盛139246256731 小时前
破局 Type‑C 切换器痛点@ACP#GSV6155+LH3828/GSV2221+LH3828 黄金方案
c语言·开发语言·网络·人工智能·嵌入式硬件·计算机外设·电脑
不爱吃炸鸡柳1 小时前
单链表专题(完整代码版)
数据结构·算法·链表
Ricky_Theseus1 小时前
C++右值引用
java·开发语言·c++