简单消息队列
1、MessageQueue
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
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 能收到