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 能收到
相关推荐
chilavert3181 小时前
技术演进中的开发沉思-194 JavaScript: Prototype 框架
开发语言·javascript·原型模式
2501_941237451 小时前
高性能计算通信库
开发语言·c++·算法
绝无仅有1 小时前
电商大厂技术面试:分布式扩展与系统设计问题解析
后端·面试·架构
杜子不疼.1 小时前
【C++】红黑树为什么比AVL快?用C++亲手实现告诉你答案
开发语言·c++
程序猿追1 小时前
Ascend C编程范式总结:与CUDA的异同对比
c语言·开发语言·算法
float_六七1 小时前
SQL中=与IS的区别:关键用法解析
java·数据库·sql
rit84324992 小时前
配置Spring框架以连接SQL Server数据库
java·数据库·spring
Victor3562 小时前
Redis(133)Redis的对象共享机制是什么?
后端
Alang2 小时前
【LM-PDF】一个大模型时代的 PDF 极速预览方案是如何实现的?
前端·人工智能·后端