优化事件总线的实现。
首先,哈希Map的线程安全问题,并建议使用ConcurrentHashMap。
执行回调时的性能瓶颈,通过多线程和线程池来提高效率。实现事件的订阅和取消订阅功能,以及如何处理同步与异步执行的需求。
最后,代码的安全性和用户体验的提升,展示了同步与异步的区别。
优化代码
package com.mgiot.application.EventEmitterCore;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @program: device-platform
* @description:
* @author:
* @create: 2024-08-26 08:48
**/
public class EventEmitter {
private final Map<String, List<Callback>> eventBus = new ConcurrentHashMap<>();
private static final ExecutorService threadPoll = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
public EventEmitter emit(boolean async, String eventName, Object ...args) {
if(!checkEmitter(eventName)) {
return this;
}
List<Callback> callbackList = eventBus.get(eventName);
if(callbackList.isEmpty()) {
return this;
}
Runnable task = new Runnable() {
@Override
public void run() {
callbackList.forEach(callback -> {
if(callback instanceof ArgsCallback argsCallback) {
argsCallback.invoke(args);
return;
}
((NoArgsCallback)callback).invoke();
});
}
};
/*在某些情况下,开发者需要保证任务的同步执行,以避免在交给其他线程处理时出现错误或遗漏。*/
if(async) {
task.run();
return this;
}
// 多线程 异步执行
threadPoll.execute(task);
return this;
}
// 默认采用线程池的方法
public EventEmitter emit(String eventName, Object ...args) {
return emit(false, eventName, args);
}
private boolean checkEmitter(String eventName) {
if (!eventBus.containsKey(eventName)) {
eventBus.put(eventName, new LinkedList<>());
return false;
}
return true;
}
public EventEmitter on(String eventName, Callback callback) {
checkEmitter(eventName);
eventBus.get(eventName).add(callback);
return this;
}
public EventEmitter on(String eventName, NoArgsCallback noArgsCallback) {
return on(eventName, (Callback)noArgsCallback);
}
public EventEmitter on(String eventName, ArgsCallback argsCallback) {
return on(eventName, (Callback)argsCallback);
}
// 取消订阅
public EventEmitter remove(String eventName, Callback callback) {
if(!eventBus.containsKey(eventName)) {
return this;
}
eventBus.get(eventName).remove(callback);
return this;
}
// 移除事件
public EventEmitter remove(String eventName) {
eventBus.remove(eventName);
return this;
}
}
执行
public static void main(String[] args) {
EventEmitter emitter = new EventEmitter();
new Thread(new Runnable() {
@Override
public void run() {
int msg = 0;
while (true) {
emitter.emit("打招呼", "你好:" + msg);
msg++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}).start();
ArgsCallback hello3Callback = new ArgsCallback() {
@Override
public void invoke(Object[] args) {
System.out.println("收到问候语3:" + Arrays.toString(args));
}
};
emitter.on("打招呼", new ArgsCallback() {
@Override
public void invoke(Object[] args) {
System.out.println("收到问候语1:" + Arrays.toString(args));
}
}).on("打招呼", new ArgsCallback() {
@Override
public void invoke(Object[] args) {
System.out.println("收到问候语2:" + Arrays.toString(args));
}
}).on("打招呼", hello3Callback);
// emitter.remove("打招呼", hello3Callback);
// emitter.remove("打招呼");
}
同步/异步 区别测试
public static void main(String[] args) {
EventEmitter emitter = new EventEmitter();
final int[] msg = {0};
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
System.out.println("触发前 消息msg是:" + msg[0]);
emitter.emit("交朋友", msg[0]);
System.out.println("触发后 消息msg是:" + msg[0]);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}).start();
emitter.on("交朋友", new ArgsCallback() {
@Override
public void invoke(Object[] args) {
msg[0] = (int) args[0] + 10;
System.out.println("交到新朋友:" + msg[0]);
}
});
}
异步执行
同步执行