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 能收到
相关推荐
yugi987838几秒前
基于Matlab的晴空指数计算实现
开发语言·算法·matlab
song150265372983 分钟前
空间站太阳能帆板电池 组件性能测试 AM0太阳光模拟器
开发语言·python
守护砂之国泰裤辣4 分钟前
Windows+docker下简单kafka测试联调
java·运维·spring boot·docker·容器
不会c嘎嘎5 分钟前
QT中的常用控件 (三)
开发语言·qt
代码方舟5 分钟前
Java企业级风控实战:对接天远多头借贷行业风险版API构建信贷评分引擎
java·开发语言
数据小馒头9 分钟前
MySQL文本处理:全库搜索慢?正则清洗难?掌握这 3 个方法
后端
闫有尽意无琼10 分钟前
Qt局部变量“遮蔽(shadow)”成员变量导致lambda传参报错
开发语言·qt
星火开发设计10 分钟前
Python数列表完全指南:从基础到实战
开发语言·python·学习·list·编程·知识·期末考试
工程师00713 分钟前
C# 动态编程(基于 dynamic 类型)
开发语言·c#·dynamic·动态编程
星浩AI15 分钟前
LCEL:打造可观测、可扩展、可部署的 LangChain 应用
人工智能·后端·python