模拟Spring自实现监听器
模拟Spring自实现监听器
注意:在toC的项目中禁止使用延时发布事件(事件发布后延时执行),采用sleep方式,会造成线程池任务堆积,从而执行拒绝策略,同时等待队列中任务排队等待时间过长,造成任务执行的积压
组件:
事件(Event):即监听什么。如任务即将执行、任务执行完毕
监听器(Listener):谁来监听,<E extends Event> :E,对什么时间感兴趣(监听特定类型的事件)
广播器(Multicaster):发布事件、添加/移除监听器
事件触发机制:事件什么时候发布
1、事件 抽象类Event,其他要监控的事件继承它
/** * 事件 * * @author yangyongjie * @date 2020/9/30 * @desc */ public abstract class Event<T> { /** * 事件自身资源,用来发布任务时传递一些参数信息 */ protected T source; /** * 事件发生时间 */ private final long timestamp; public Event(T source) { this.source = source; this.timestamp = System.currentTimeMillis(); } public T getSource() { return source; } public void setSource(T source) { this.source = source; } public long getTimestamp() { return timestamp; } }
如流程结束事件:
/** * 审批流程结束事件 * * @author yangyongjie * @date 2020/10/15 * @desc */ public class AuditFlowFinishEvent extends Event<AuditFlow> { public AuditFlowFinishEvent(AuditFlow auditFlow) { super(auditFlow); } }
2、监听器接口 Listener,自定义监听器实现它;泛型E表示要监听的事件
/** * 监听器 * * @author yangyongjie * @date 2020/9/30 * @desc */ public interface Listener<E extends Event> { /** * 当事件发生做一些事情 * * @param event */ void onEvent(E event); }
如:审核流程结束监听器
/** * 审核流程结束监听器 * * @author yangyongjie * @date 2020/10/15 * @desc */ @Component public class AuditFlowFinishListener implements Listener<AuditFlowFinishEvent> { private static final Logger LOGGER = LoggerFactory.getLogger(AuditFlowFinishListener.class); @Override public void onEvent(AuditFlowFinishEvent event) { AuditFlow auditFlow = event.getSource(); LOGGER.info("流程结束监听器工作了!"); } }
3、广播器,管理监听器,发布事件 (需注入到Spring容器中)
V1.0:
1)广播器接口:
/** * 事件广播器 * * @author yangyongjie * @date 2020/9/30 * @desc */ public interface EventMulticaster { /** * 添加监听器 * * @param listener */ void addListener(Listener<?> listener); /** * 移除监听器 * * @param listener */ void removeListener(Listener<?> listener); /** * 发布事件 * * @param event */ void multicastEvent(Event event); }
2)广播器实现类:
import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; /** * 广播器(事件发布器) * * @author yangyongjie * @date 2020/10/15 * @desc */ @Component public class SimpleEventMulticaster implements EventMulticaster, ApplicationContextAware { private static final Logger LOGGER = LoggerFactory.getLogger(SimpleEventMulticaster.class); private final Set<Listener<?>> listeners = new LinkedHashSet<>(); /** * 创建一个执行监听器线程池,核心线程数为1,最大线程数为5,线程空闲时间为60s,拒绝策略为打印日志并直接执行被拒绝的任务 */ private static final ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(1, 5, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(50), new CustomThreadFactory("simpleEventMulticaster"), (r, executor) -> { LOGGER.error("Task:{},rejected from:{}", r.toString(), executor.toString()); // 直接执行被拒绝的任务,JVM另起线程执行 r.run(); }); @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { // 获取容器中实现Listener接口的监听器,并添加到listeners缓存中 Map<String, Listener> listenerMap = applicationContext.getBeansOfType(Listener.class); for (Map.Entry<String, Listener> entry : listenerMap.entrySet()) { addListener(entry.getValue()); } } @Override public void addListener(Listener<?> listener) { this.listeners.add(listener); } @Override public void removeListener(Listener<?> listener) { this.listeners.remove(listener); } @Override public void multicastEvent(final Event event) { multicastEvent(event, true); } /** * 是否异步,默认true * * @param event * @param async */ public void multicastEvent(final Event event, boolean async) { Class eventClass = event.getClass(); Set<Listener> interestedListeners = getInterestedListeners(eventClass); // 事件发生,异步调用监听器的事件方法 if (async) { for (final Listener listener : interestedListeners) { EXECUTOR.execute(() -> listener.onEvent(event)); } } else { for (final Listener listener : interestedListeners) { listener.onEvent(event); } } } /** * 获取对当前事件感兴趣的监听器 * * @param eventClass */ private Set<Listener> getInterestedListeners(Class eventClass) { // 存放监听对发布事件感兴趣的监听器 Set<Listener> interestedListeners = new LinkedHashSet<>(); for (Listener listener : listeners) { // 获取监听器的泛型类型 ParameterizedType parameterizedType = (ParameterizedType) listener.getClass().getGenericInterfaces()[0]; Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); Listener filterListener = null; for (Type actualTypeArgument : actualTypeArguments) { if (StringUtils.equals(eventClass.getName(), actualTypeArgument.getTypeName())) { filterListener = listener; } } if (filterListener != null) { interestedListeners.add(filterListener); } } return interestedListeners; } }
注1:1.8之前版本 actualTypeArgument.getTypeName() 替换成 ((Class) actualTypeArgument).getName() ;并替换掉 Lambda表达式
注2:若在监听器的onEvent方法上加了@Transactional注解,那么获取到的监听器的对象就是代理对象,在获取监听器泛型的时候会有问题,需要拿到被代理的目标类对象,然后再去获取泛型类型:
修改后的getInterestedListeners()方法的for循环第一行:
ParameterizedType parameterizedType = (ParameterizedType) AopTargetUtil.getTarget(listener).getClass().getGenericInterfaces()[0];
V2.0:
1)广播器接口:
/** * 事件广播器 * * @author yangyongjie * @date 2020/9/30 * @desc */ public interface EventMulticaster { /** * 添加监听器 * * @param listener */ void addListener(Listener<?> listener); /** * 移除监听器 * * @param listener */ void removeListener(Listener<?> listener); /** * 发布事件,默认异步执行监听 * * @param event */ void multicastEvent(Event<?> event); /** * 发布事件,按参数确定异步还是同步执行监听 * * @param event * @param async */ void multicastEvent(Event<?> event, boolean async); }
2)广播器实现类:
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.aop.support.AopUtils; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.core.ResolvableType; import org.springframework.stereotype.Component; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; /** * 广播器(事件发布器) * * @author yangyongjie * @date 2021/1/28 */ @Component public class SimpleEventMulticaster implements EventMulticaster, ApplicationContextAware { private static final Logger LOGGER = LoggerFactory.getLogger(SimpleEventMulticaster.class); /** * 所有监听器的集合 */ private final Set<Listener<?>> listeners = new LinkedHashSet<>(); /** * 创建一个执行监听器线程池,核心线程数为2,最大线程数为5,线程空闲时间为60s,拒绝策略为打印日志并直接执行被拒绝的任务 * 线程数和队列依具体业务而定 */ private static final ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor( 2, 5, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(50), new CustomThreadFactory("simpleEventMulticaster"), (r, executor) -> { LOGGER.error("Task:{},rejected from:{}", r.toString(), executor.toString()); // 直接执行被拒绝的任务,JVM另起线程执行 r.run(); }); @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { // 获取容器中实现Listener接口的监听器,并添加到listeners缓存中 Map<String, Listener> listenerMap = applicationContext.getBeansOfType(Listener.class); for (Map.Entry<String, Listener> entry : listenerMap.entrySet()) { addListener(entry.getValue()); } } @Override public void addListener(Listener<?> listener) { this.listeners.add(listener); } @Override public void removeListener(Listener<?> listener) { this.listeners.remove(listener); } /** * 发布事件 * * @param event */ @Override public void multicastEvent(Event<?> event) { multicastEvent(event, true); } @Override public void multicastEvent(Event<?> event, boolean async) { Class eventClass = event.getClass(); Set<Listener<?>> interestedListeners = getInterestedListeners(eventClass); // 事件发生,异步调用监听器的事件方法 for (Listener<?> listener : interestedListeners) { if (async) { EXECUTOR.execute(() -> invokeListener(listener, event)); } else { invokeListener(listener, event); } } } /** * 触发监听器事件处理 * * @param listener * @param event */ private void invokeListener(Listener listener, Event event) { try { listener.onEvent(event); } catch (Exception e) { LOGGER.error(e.getMessage(), e); } } /** * 获取对当前事件感兴趣的监听器(监听了当前事件或当前事件的父事件) * * @param eventClass */ private Set<Listener<?>> getInterestedListeners(Class eventClass) { // 存放监听对发布事件感兴趣的监听器 Set<Listener<?>> interestedListeners = new LinkedHashSet<>(); for (Listener<?> listener : listeners) { // 避免listener被aop代理,因此获取其被代理的listener Class<?> targetClass = AopUtils.getTargetClass(listener); // 获取监听器的泛型类型(即监听器监听的事件类型) ResolvableType genericEventType = ResolvableType.forClass(targetClass).as(Listener.class).getGeneric(); // 监听器监听的事件类型是否是发布事件类型的父类 或与发布的事件类型相同 if (genericEventType.isAssignableFrom(eventClass)) { interestedListeners.add(listener); } } return interestedListeners; } }
4、使用广播器发布事件(在事件源中发布事件)
@Autowired private EventMulticaster eventMulticaster; // 发布事件 eventMulticaster.multicastEvent(new AuditFlowFinishEvent(auditFlow));
V3.0
改进:
痛点:发布事件需要注入EventMulticaster依赖,非常麻烦
目标:通过工具类直接发布事件,工具类中有EventMulticaster的实例,且工具类不需要作为bean注入到Spring容器中
1、新建EventCaster:
public class EventCaster {
private static SimpleEventMulticaster simpleEventMulticaster;
public static void SetSimpleEventMulticaster(SimpleEventMulticaster simpleEventMulticaster) {
EventCaster.simpleEventMulticaster = simpleEventMulticaster;
}
/**
* 异步的事件发布
*
* @param event
*/
public static void multicastEvent(Event<?> event) {
simpleEventMulticaster.multicastEvent(event);
}
/**
* 自定义同步or异步的事件发布
*
* @param event
* @param async
*/
public static void multicastEvent(Event<?> event, boolean async) {
simpleEventMulticaster.multicastEvent(event, async);
}
}
2、修改SimpleEventMulticaster,为EventCaster设置SimpleEventMulticaster的实例
/**
* 广播器(事件发布器)
*
* @author yangyongjie
* @date 2020/10/15
*/
@Component
public class SimpleEventMulticaster implements EventMulticaster, ApplicationContextAware, InitializingBean {
private static final Logger LOGGER = LoggerFactory.getLogger(SimpleEventMulticaster.class);
private final Set<Listener<?>> listeners = new LinkedHashSet<>();
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
// 获取容器中实现Listener接口的监听器,并添加到listeners缓存中
Map<String, Listener> listenerMap = applicationContext.getBeansOfType(Listener.class);
for (Map.Entry<String, Listener> entry : listenerMap.entrySet()) {
addListener(entry.getValue());
}
}
@Override
public void afterPropertiesSet() {
// 为EventCaster设置SimpleEventMulticaster的实例
EventCaster.SetSimpleEventMulticaster(this);
}
@Override
public void addListener(Listener<?> listener) {
this.listeners.add(listener);
}
@Override
public void removeListener(Listener<?> listener) {
this.listeners.remove(listener);
}
@Override
public void multicastEvent(Event<?> event) {
multicastEvent(event, true);
}
@Override
public void multicastEvent(Event<?> event, boolean async) {
Class<?> eventClass = event.getClass();
Set<Listener<?>> interestedListeners = getInterestedListeners(eventClass);
// 事件发生,异步调用监听器的事件方法
for (Listener<?> listener : interestedListeners) {
if (async) {
ThreadPoolUtil.execute(() -> invokeListener(listener, event));
} else {
invokeListener(listener, event);
}
}
}
private void invokeListener(Listener listener, Event event) {
try {
// 睡眠1s等待前面的事务提交
Thread.sleep(5000);
listener.onEvent(event);
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
Thread.currentThread().interrupt();
}
}
/**
* 获取对当前事件感兴趣的监听器(监听了当前事件或当前事件的父事件)
*
* @param eventClass
*/
private Set<Listener<?>> getInterestedListeners(Class<?> eventClass) {
// 存放监听对发布事件感兴趣的监听器
Set<Listener<?>> interestedListeners = new LinkedHashSet<>();
for (Listener<?> listener : listeners) {
// 避免listener被aop代理,因此获取其被代理的listener
Class<?> targetClass = AopUtils.getTargetClass(listener);
// 获取监听器的泛型类型(即监听器监听的事件类型)
ResolvableType genericEventType = ResolvableType.forClass(targetClass).as(Listener.class).getGeneric();
// 监听器监听的事件类型是否是发布事件类型的父类 或与发布的事件类型相同
boolean interested = genericEventType.isAssignableFrom(eventClass);
if (interested) {
interestedListeners.add(listener);
}
}
return interestedListeners;
}
}
3、发布事件:
EventCaster.multicastEvent(new NoUpdateCalendarEvent(highEfficientMovie));
v 4.0
支持事件延迟发布
EventMulticaster 增加:
/**
* 发布事件
*
* @param event 事件实例
* @param async 是否异步
* @param delayMillis 延迟毫秒数
*/
void multicastEvent(Event<?> event, boolean async, long delayMillis);
SimpleEventMulticaster:
/**
* 广播器(事件发布器)
*
* @author yangyongjie
* @date 2020/10/15
*/
@Component
public class SimpleEventMulticaster implements EventMulticaster, ApplicationContextAware {
private static final Logger LOGGER = LoggerFactory.getLogger(SimpleEventMulticaster.class);
private final Set<Listener<?>> listeners = new LinkedHashSet<>();
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
// 获取容器中实现Listener接口的监听器,并添加到listeners缓存中
Map<String, Listener> listenerMap = applicationContext.getBeansOfType(Listener.class);
for (Map.Entry<String, Listener> entry : listenerMap.entrySet()) {
addListener(entry.getValue());
}
// 为EventCaster设置SimpleEventMulticaster的实例
EventCaster.SetSimpleEventMulticaster(this);
}
@Override
public void addListener(Listener<?> listener) {
this.listeners.add(listener);
}
@Override
public void removeListener(Listener<?> listener) {
this.listeners.remove(listener);
}
@Override
public void multicastEvent(Event<?> event) {
multicastEvent(event, true);
}
@Override
public void multicastEvent(Event<?> event, boolean async) {
multicastEvent(event, async, 0L);
}
@Override
public void multicastEvent(Event<?> event, boolean async, long delayMillis) {
Class<?> eventClass = event.getClass();
Set<Listener<?>> interestedListeners = getInterestedListeners(eventClass);
// 事件发生,异步调用监听器的事件方法
for (Listener<?> listener : interestedListeners) {
if (async) {
ThreadPoolUtil.execute(() -> {
// 调用监听器的执行
invokeListener(listener, event, delayMillis);
});
} else {
// 调用监听器的执行
invokeListener(listener, event, delayMillis);
}
}
}
/**
* 调用监听器执行
*
* @param listener
* @param event
*/
private void invokeListener(Listener listener, Event<?> event, long delayMillis) {
try {
// 如果延迟时间不为0,则睡眠等待
if (delayMillis != 0) {
Thread.sleep(delayMillis);
}
listener.onEvent(event);
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
}
/**
* 获取对当前事件感兴趣的监听器(监听了当前事件或当前事件的父事件)
*
* @param eventClass
*/
private Set<Listener<?>> getInterestedListeners(Class<?> eventClass) {
// 存放监听对发布事件感兴趣的监听器
Set<Listener<?>> interestedListeners = new LinkedHashSet<>();
for (Listener<?> listener : listeners) {
// 避免listener被aop代理,因此获取其被代理的listener
Class<?> targetClass = AopUtils.getTargetClass(listener);
// 获取监听器的泛型类型(即监听器监听的事件类型)
ResolvableType genericEventType = ResolvableType.forClass(targetClass).as(Listener.class).getGeneric();
// 监听器监听的事件类型是否是发布事件类型的父类 或与发布的事件类型相同
boolean interested = genericEventType.isAssignableFrom(eventClass);
if (interested) {
interestedListeners.add(listener);
}
}
return interestedListeners;
}
}
EventCaster 增加:
/**
* 支持事件延迟发布
* @param event
* @param async
* @param delayMillis
*/
public static void multicastEvent(Event<?> event, boolean async, long delayMillis) {
simpleEventMulticaster.multicastEvent(event,async,delayMillis);
}
最终代码:
Event:
/**
* 事件
*
* @author yangyongjie
* @date 2020/9/30
*/
public abstract class Event<T> {
/**
* 事件自身资源,用来发布任务时传递一些参数信息
*/
protected T source;
/**
* 事件发生时间
*/
private final long timestamp;
protected Event(T source) {
this.source = source;
this.timestamp = System.currentTimeMillis();
}
public T getSource() {
return source;
}
public void setSource(T source) {
this.source = source;
}
public long getTimestamp() {
return timestamp;
}
}
EventCaster:
/**
* 事件发布器
*
* @author yangyongjie
*/
public class EventCaster {
private static SimpleEventMulticaster simpleEventMulticaster;
public static void SetSimpleEventMulticaster(SimpleEventMulticaster simpleEventMulticaster) {
EventCaster.simpleEventMulticaster = simpleEventMulticaster;
}
/**
* 异步的事件发布
*
* @param event
*/
public static void multicastEvent(Event<?> event) {
simpleEventMulticaster.multicastEvent(event);
}
/**
* 自定义同步or异步的事件发布
*
* @param event
* @param async
*/
public static void multicastEvent(Event<?> event, boolean async) {
simpleEventMulticaster.multicastEvent(event, async);
}
/**
* 支持事件延迟发布
*
* @param event
* @param async
* @param delayMillis
*/
public static void multicastEvent(Event<?> event, boolean async, long delayMillis) {
simpleEventMulticaster.multicastEvent(event, async, delayMillis);
}
}
EventMulticaster:
/**
* 事件广播器
*
* @author yangyongjie
* @date 2020/9/30
*/
public interface EventMulticaster {
/**
* 添加监听器
*
* @param listener
*/
void addListener(Listener<?> listener);
/**
* 移除监听器
*
* @param listener
*/
void removeListener(Listener<?> listener);
/**
* 发布事件,默认异步执行监听
*
* @param event
*/
void multicastEvent(Event<?> event);
/**
* 发布事件,按参数确定异步还是同步执行监听
*
* @param event
* @param async
*/
void multicastEvent(Event<?> event, boolean async);
/**
* 发布事件
*
* @param event 事件实例
* @param async 是否异步
* @param delayMillis 延迟毫秒数
*/
void multicastEvent(Event<?> event, boolean async, long delayMillis);
}
Listener:
/**
* 监听器
*
* @author yangyongjie
* @date 2020/9/30
*/
public interface Listener<E extends Event<?>> {
/**
* 当事件发生做一些事件
*
* @param event 事件
* @throws Exception
*/
void onEvent(E event) throws Exception;
}
ListenerExecutors:
/**
* 监听器专用线程池
*
* @author yangyongjie
*/
public class ListenerExecutors {
private ListenerExecutors() {
}
private static final Logger LOGGER = LoggerFactory.getLogger(ListenerExecutors.class);
/**
* cpu核心数
*/
private static final int CPU_CORE = Runtime.getRuntime().availableProcessors();
/**
* 核心线程数
*/
private static final int HYPER_THREAD = CPU_CORE * 2;
/**
* 线程池
*/
private static final ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(
CPU_CORE,
HYPER_THREAD,
60,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(10000),
new ThreadPoolUtil.CustomThreadFactory("common"),
(r, executor) -> {
// 打印日志
String taskName = r.toString();
LOGGER.error("Task:{}, rejected from common", taskName);
// 直接执行被拒绝的任务,JVM另起线程执行
r.run();
}
);
/**
* 提交线程池处理
*
* @param runnable 任务
*/
protected static void execute(Runnable runnable) {
EXECUTOR.execute(runnable);
}
/**
* 提交线程池处理任务,可获取返回值
*
* @param callable 任务
* @param <T> 返回值类型
* @return Future
*/
protected static <T> Future<T> submit(Callable<T> callable) {
return EXECUTOR.submit(callable);
}
}
SimpleEventMulticaster:
/**
* 广播器(事件发布器)
*
* @author yangyongjie
* @date 2020/10/15
*/
@Component
public class SimpleEventMulticaster implements EventMulticaster, ApplicationContextAware {
private static final Logger LOGGER = LoggerFactory.getLogger(SimpleEventMulticaster.class);
private final Set<Listener<?>> listeners = new LinkedHashSet<>();
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
// 获取容器中实现Listener接口的监听器,并添加到listeners缓存中
Map<String, Listener> listenerMap = applicationContext.getBeansOfType(Listener.class);
for (Map.Entry<String, Listener> entry : listenerMap.entrySet()) {
addListener(entry.getValue());
}
// 为EventCaster设置SimpleEventMulticaster的实例
EventCaster.SetSimpleEventMulticaster(this);
}
@Override
public void addListener(Listener<?> listener) {
this.listeners.add(listener);
}
@Override
public void removeListener(Listener<?> listener) {
this.listeners.remove(listener);
}
@Override
public void multicastEvent(Event<?> event) {
multicastEvent(event, true);
}
@Override
public void multicastEvent(Event<?> event, boolean async) {
multicastEvent(event, async, 0L);
}
@Override
public void multicastEvent(Event<?> event, boolean async, long delayMillis) {
Class<?> eventClass = event.getClass();
Set<Listener<?>> interestedListeners = getInterestedListeners(eventClass);
// 事件发生,异步调用监听器的事件方法
for (Listener<?> listener : interestedListeners) {
if (async) {
ListenerExecutors.execute(() -> {
// 调用监听器的执行
invokeListener(listener, event, delayMillis);
});
} else {
// 调用监听器的执行
invokeListener(listener, event, delayMillis);
}
}
}
/**
* 调用监听器执行
*
* @param listener
* @param event
*/
private void invokeListener(Listener listener, Event<?> event, long delayMillis) {
try {
// 如果延迟时间不为0,则睡眠等待
if (delayMillis != 0) {
Thread.sleep(delayMillis);
}
listener.onEvent(event);
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
}
/**
* 获取对当前事件感兴趣的监听器(监听了当前事件或当前事件的父事件)
*
* @param eventClass
*/
private Set<Listener<?>> getInterestedListeners(Class<?> eventClass) {
// 存放监听对发布事件感兴趣的监听器
Set<Listener<?>> interestedListeners = new LinkedHashSet<>();
for (Listener<?> listener : listeners) {
// 避免listener被aop代理,因此获取其被代理的listener
Class<?> targetClass = AopUtils.getTargetClass(listener);
// 获取监听器的泛型类型(即监听器监听的事件类型)
ResolvableType genericEventType = ResolvableType.forClass(targetClass).as(Listener.class).getGeneric();
// 监听器监听的事件类型是否是发布事件类型的父类 或与发布的事件类型相同
boolean interested = genericEventType.isAssignableFrom(eventClass);
if (interested) {
interestedListeners.add(listener);
}
}
return interestedListeners;
}
}
依赖ThreadPoolUtil:
查看代码
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nonnull;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 线程池工具
*
* @author liangjinxin
*/
public final class ThreadPoolUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(ThreadPoolUtil.class);
/**
* cpu核心数
*/
public static final int CPU_CORE = Runtime.getRuntime().availableProcessors();
/**
* 核心线程数
*/
public static final int HYPER_THREAD = CPU_CORE * 2;
/**
* 线程池
*/
private static final ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(
CPU_CORE,
HYPER_THREAD,
60,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(10000),
new CustomThreadFactory("common"),
(r, executor) -> {
// 打印日志
String taskName = r.toString();
LOGGER.error("Task:{}, rejected from common", taskName);
// 当前提交任务的线程来直接执行被拒绝的任务,非另起线程执行!
r.run();
}
);
private ThreadPoolUtil() {
}
/**
* 提交线程池处理
*
* @param runnable 任务
*/
public static void execute(Runnable runnable) {
EXECUTOR.execute(runnable);
}
/**
* 提交线程池处理任务,可获取返回值
*
* @param callable 任务
* @param <T> 返回值类型
* @return Future
*/
public static <T> Future<T> submit(Callable<T> callable) {
return EXECUTOR.submit(callable);
}
/**
* 创建线程的工厂,指定有意义的线程组名称,方便回溯
*
* @author yangyongjie
*/
public static class CustomThreadFactory implements ThreadFactory {
/**
* 线程池中的线程名称前缀
*/
private final String namePrefix;
/**
* 用于线程的名称递增排序
*/
private final AtomicInteger atomicInteger = new AtomicInteger(1);
public CustomThreadFactory(String whatFeatureOfGroup) {
this.namePrefix = "From CustomThreadFactory-" + whatFeatureOfGroup + "-worker-";
}
@Override
public Thread newThread(@Nonnull Runnable r) {
String name = namePrefix + atomicInteger.getAndIncrement();
return new Thread(r, name);
}
}
}
附录:
1)AopTargetUtil:
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.aop.framework.AdvisedSupport; import org.springframework.aop.framework.AopProxy; import org.springframework.aop.support.AopUtils; import java.lang.reflect.Field; /** * 通过代理对象获取被代理的目标对象 * * @author yangyongjie * @date 2020/12/10 * @desc */ public class AopTargetUtil { private static final Logger LOGGER = LoggerFactory.getLogger(AopTargetUtil.class); private AopTargetUtil() { } /** * 获取 目标对象 * * @param proxy 代理对象 * @return * @throws Exception */ public static Object getTarget(Object proxy) { // 不是代理对象,即没有被aop代理,直接返回 if (!AopUtils.isAopProxy(proxy)) { return proxy; } try { // cglibProxy if (AopUtils.isCglibProxy(proxy)) { return getCglibProxyTargetObject(proxy); // jdkDynamicProxy } else { return getJdkDynamicProxyTargetObject(proxy); } } catch (Exception e) { LOGGER.error("获取被代理类对象异常:" + e.getMessage(), e); return proxy; } } /** * CGLIB方式被代理类的获取 * * @param proxy * @return * @throws Exception */ private static Object getCglibProxyTargetObject(Object proxy) throws Exception { Field h = proxy.getClass().getDeclaredField("CGLIB$CALLBACK_0"); h.setAccessible(true); Object dynamicAdvisedInterceptor = h.get(proxy); Field advised = dynamicAdvisedInterceptor.getClass().getDeclaredField("advised"); advised.setAccessible(true); Object target = ((AdvisedSupport) advised.get(dynamicAdvisedInterceptor)).getTargetSource().getTarget(); return target; } /** * JDK动态代理方式被代理类的获取 * * @param proxy * @return * @throws Exception */ private static Object getJdkDynamicProxyTargetObject(Object proxy) throws Exception { Field h = proxy.getClass().getSuperclass().getDeclaredField("h"); h.setAccessible(true); AopProxy aopProxy = (AopProxy) h.get(proxy); Field advised = aopProxy.getClass().getDeclaredField("advised"); advised.setAccessible(true); Object target = ((AdvisedSupport) advised.get(aopProxy)).getTargetSource().getTarget(); return target; } }
2)org.springframework.aop.support.AopUtils:
/* * Copyright 2002-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.aop.support; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import org.springframework.aop.Advisor; import org.springframework.aop.AopInvocationException; import org.springframework.aop.IntroductionAdvisor; import org.springframework.aop.IntroductionAwareMethodMatcher; import org.springframework.aop.MethodMatcher; import org.springframework.aop.Pointcut; import org.springframework.aop.PointcutAdvisor; import org.springframework.aop.SpringProxy; import org.springframework.aop.TargetClassAware; import org.springframework.core.BridgeMethodResolver; import org.springframework.core.MethodIntrospector; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.ReflectionUtils; /** * Utility methods for AOP support code. * * <p>Mainly for internal use within Spring's AOP support. * * <p>See {@link org.springframework.aop.framework.AopProxyUtils} for a * collection of framework-specific AOP utility methods which depend * on internals of Spring's AOP framework implementation. * * @author Rod Johnson * @author Juergen Hoeller * @author Rob Harrop * @see org.springframework.aop.framework.AopProxyUtils */ public abstract class AopUtils { /** * Check whether the given object is a JDK dynamic proxy or a CGLIB proxy. * <p>This method additionally checks if the given object is an instance * of {@link SpringProxy}. * @param object the object to check * @see #isJdkDynamicProxy * @see #isCglibProxy */ public static boolean isAopProxy(@Nullable Object object) { return (object instanceof SpringProxy && (Proxy.isProxyClass(object.getClass()) || object.getClass().getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR))); } /** * Check whether the given object is a JDK dynamic proxy. * <p>This method goes beyond the implementation of * {@link Proxy#isProxyClass(Class)} by additionally checking if the * given object is an instance of {@link SpringProxy}. * @param object the object to check * @see java.lang.reflect.Proxy#isProxyClass */ public static boolean isJdkDynamicProxy(@Nullable Object object) { return (object instanceof SpringProxy && Proxy.isProxyClass(object.getClass())); } /** * Check whether the given object is a CGLIB proxy. * <p>This method goes beyond the implementation of * {@link ClassUtils#isCglibProxy(Object)} by additionally checking if * the given object is an instance of {@link SpringProxy}. * @param object the object to check * @see ClassUtils#isCglibProxy(Object) */ public static boolean isCglibProxy(@Nullable Object object) { return (object instanceof SpringProxy && object.getClass().getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)); } /** * Determine the target class of the given bean instance which might be an AOP proxy. * <p>Returns the target class for an AOP proxy or the plain class otherwise. * @param candidate the instance to check (might be an AOP proxy) * @return the target class (or the plain class of the given object as fallback; * never {@code null}) * @see org.springframework.aop.TargetClassAware#getTargetClass() * @see org.springframework.aop.framework.AopProxyUtils#ultimateTargetClass(Object) */ public static Class<?> getTargetClass(Object candidate) { Assert.notNull(candidate, "Candidate object must not be null"); Class<?> result = null; if (candidate instanceof TargetClassAware) { result = ((TargetClassAware) candidate).getTargetClass(); } if (result == null) { result = (isCglibProxy(candidate) ? candidate.getClass().getSuperclass() : candidate.getClass()); } return result; } /** * Select an invocable method on the target type: either the given method itself * if actually exposed on the target type, or otherwise a corresponding method * on one of the target type's interfaces or on the target type itself. * @param method the method to check * @param targetType the target type to search methods on (typically an AOP proxy) * @return a corresponding invocable method on the target type * @throws IllegalStateException if the given method is not invocable on the given * target type (typically due to a proxy mismatch) * @since 4.3 * @see MethodIntrospector#selectInvocableMethod(Method, Class) */ public static Method selectInvocableMethod(Method method, @Nullable Class<?> targetType) { if (targetType == null) { return method; } Method methodToUse = MethodIntrospector.selectInvocableMethod(method, targetType); if (Modifier.isPrivate(methodToUse.getModifiers()) && !Modifier.isStatic(methodToUse.getModifiers()) && SpringProxy.class.isAssignableFrom(targetType)) { throw new IllegalStateException(String.format( "Need to invoke method '%s' found on proxy for target class '%s' but cannot " + "be delegated to target bean. Switch its visibility to package or protected.", method.getName(), method.getDeclaringClass().getSimpleName())); } return methodToUse; } /** * Determine whether the given method is an "equals" method. * @see java.lang.Object#equals */ public static boolean isEqualsMethod(@Nullable Method method) { return ReflectionUtils.isEqualsMethod(method); } /** * Determine whether the given method is a "hashCode" method. * @see java.lang.Object#hashCode */ public static boolean isHashCodeMethod(@Nullable Method method) { return ReflectionUtils.isHashCodeMethod(method); } /** * Determine whether the given method is a "toString" method. * @see java.lang.Object#toString() */ public static boolean isToStringMethod(@Nullable Method method) { return ReflectionUtils.isToStringMethod(method); } /** * Determine whether the given method is a "finalize" method. * @see java.lang.Object#finalize() */ public static boolean isFinalizeMethod(@Nullable Method method) { return (method != null && method.getName().equals("finalize") && method.getParameterCount() == 0); } /** * Given a method, which may come from an interface, and a target class used * in the current AOP invocation, find the corresponding target method if there * is one. E.g. the method may be {@code IFoo.bar()} and the target class * may be {@code DefaultFoo}. In this case, the method may be * {@code DefaultFoo.bar()}. This enables attributes on that method to be found. * <p><b>NOTE:</b> In contrast to {@link org.springframework.util.ClassUtils#getMostSpecificMethod}, * this method resolves Java 5 bridge methods in order to retrieve attributes * from the <i>original</i> method definition. * @param method the method to be invoked, which may come from an interface * @param targetClass the target class for the current invocation. * May be {@code null} or may not even implement the method. * @return the specific target method, or the original method if the * {@code targetClass} doesn't implement it or is {@code null} * @see org.springframework.util.ClassUtils#getMostSpecificMethod */ public static Method getMostSpecificMethod(Method method, @Nullable Class<?> targetClass) { Class<?> specificTargetClass = (targetClass != null ? ClassUtils.getUserClass(targetClass) : null); Method resolvedMethod = ClassUtils.getMostSpecificMethod(method, specificTargetClass); // If we are dealing with method with generic parameters, find the original method. return BridgeMethodResolver.findBridgedMethod(resolvedMethod); } /** * Can the given pointcut apply at all on the given class? * <p>This is an important test as it can be used to optimize * out a pointcut for a class. * @param pc the static or dynamic pointcut to check * @param targetClass the class to test * @return whether the pointcut can apply on any method */ public static boolean canApply(Pointcut pc, Class<?> targetClass) { return canApply(pc, targetClass, false); } /** * Can the given pointcut apply at all on the given class? * <p>This is an important test as it can be used to optimize * out a pointcut for a class. * @param pc the static or dynamic pointcut to check * @param targetClass the class to test * @param hasIntroductions whether or not the advisor chain * for this bean includes any introductions * @return whether the pointcut can apply on any method */ public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) { Assert.notNull(pc, "Pointcut must not be null"); if (!pc.getClassFilter().matches(targetClass)) { return false; } MethodMatcher methodMatcher = pc.getMethodMatcher(); if (methodMatcher == MethodMatcher.TRUE) { // No need to iterate the methods if we're matching any method anyway... return true; } IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null; if (methodMatcher instanceof IntroductionAwareMethodMatcher) { introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher; } Set<Class<?>> classes = new LinkedHashSet<>(); if (!Proxy.isProxyClass(targetClass)) { classes.add(ClassUtils.getUserClass(targetClass)); } classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass)); for (Class<?> clazz : classes) { Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz); for (Method method : methods) { if (introductionAwareMethodMatcher != null ? introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) : methodMatcher.matches(method, targetClass)) { return true; } } } return false; } /** * Can the given advisor apply at all on the given class? * This is an important test as it can be used to optimize * out a advisor for a class. * @param advisor the advisor to check * @param targetClass class we're testing * @return whether the pointcut can apply on any method */ public static boolean canApply(Advisor advisor, Class<?> targetClass) { return canApply(advisor, targetClass, false); } /** * Can the given advisor apply at all on the given class? * <p>This is an important test as it can be used to optimize out a advisor for a class. * This version also takes into account introductions (for IntroductionAwareMethodMatchers). * @param advisor the advisor to check * @param targetClass class we're testing * @param hasIntroductions whether or not the advisor chain for this bean includes * any introductions * @return whether the pointcut can apply on any method */ public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) { if (advisor instanceof IntroductionAdvisor) { return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass); } else if (advisor instanceof PointcutAdvisor) { PointcutAdvisor pca = (PointcutAdvisor) advisor; return canApply(pca.getPointcut(), targetClass, hasIntroductions); } else { // It doesn't have a pointcut so we assume it applies. return true; } } /** * Determine the sublist of the {@code candidateAdvisors} list * that is applicable to the given class. * @param candidateAdvisors the Advisors to evaluate * @param clazz the target class * @return sublist of Advisors that can apply to an object of the given class * (may be the incoming List as-is) */ public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) { if (candidateAdvisors.isEmpty()) { return candidateAdvisors; } List<Advisor> eligibleAdvisors = new ArrayList<>(); for (Advisor candidate : candidateAdvisors) { if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) { eligibleAdvisors.add(candidate); } } boolean hasIntroductions = !eligibleAdvisors.isEmpty(); for (Advisor candidate : candidateAdvisors) { if (candidate instanceof IntroductionAdvisor) { // already processed continue; } if (canApply(candidate, clazz, hasIntroductions)) { eligibleAdvisors.add(candidate); } } return eligibleAdvisors; } /** * Invoke the given target via reflection, as part of an AOP method invocation. * @param target the target object * @param method the method to invoke * @param args the arguments for the method * @return the invocation result, if any * @throws Throwable if thrown by the target method * @throws org.springframework.aop.AopInvocationException in case of a reflection error */ @Nullable public static Object invokeJoinpointUsingReflection(@Nullable Object target, Method method, Object[] args) throws Throwable { // Use reflection to invoke the method. try { ReflectionUtils.makeAccessible(method); return method.invoke(target, args); } catch (InvocationTargetException ex) { // Invoked method threw a checked exception. // We must rethrow it. The client won't see the interceptor. throw ex.getTargetException(); } catch (IllegalArgumentException ex) { throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" + method + "] on target [" + target + "]", ex); } catch (IllegalAccessException ex) { throw new AopInvocationException("Could not access method [" + method + "]", ex); } } }
不依赖Spring版本:
1、事件 抽象类Event,其他要监控的事件继承它
/**
* 事件(抽象类)
* 自定义事件需继承此接口
* 事件,即监听什么,如任务即将执行事件、任务执行完毕事件
*
* @author yangyongjie
*/
public abstract class Event<T> {
/**
* 事件自身资源,用来发布任务时传递一些参数信息
*/
protected T source;
/**
* 事件发生时间
*/
private final long timestamp;
protected Event(T source) {
this.source = source;
this.timestamp = System.currentTimeMillis();
}
public T getSource() {
return source;
}
public void setSource(T source) {
this.source = source;
}
public long getTimestamp() {
return timestamp;
}
}
2、监听器接口 Listener,自定义监听器实现它;泛型E表示要监听的事件
/**
* 监听器(接口)
* 自定义监听器需实现此接口
* 监听感兴趣的事件,当事件发生时,执行一些具体的动作
*
* @author yangyongjie
*/
public interface Listener<E extends Event<?>> {
/**
* 当事件发生做一些事件
*
* @param event 事件
* @throws Exception
*/
void onEvent(E event) throws Exception;
}
3、自定义监听器接口实现Listener接口之后
①:resources下新建 META-INF/services 文件夹(SPI机制)
②:新建Listener接口全路径命名的文件
③:在文件中配置Listener实现类的全路径,每行一个
4、事件广播器接口
/**
* 事件广播器(接口)
* 发布事件、添加/移除监听器
*
* @author yangyongjie
*/
public interface EventMulticaster {
/**
* 添加监听器
*
* @param listener
*/
void addListener(Listener<?> listener);
/**
* 移除监听器
*
* @param listener
*/
void removeListener(Listener<?> listener);
/**
* 发布事件,默认异步执行监听
*
* @param event
*/
void multicastEvent(Event<?> event);
/**
* 发布事件,按参数确定异步还是同步执行监听
*
* @param event
* @param async
*/
void multicastEvent(Event<?> event, boolean async);
/**
* 发布事件
*
* @param event 事件实例
* @param async 是否异步
* @param delayMillis 延迟毫秒数
*/
void multicastEvent(Event<?> event, boolean async, long delayMillis);
}
5、广播器实现类(发布事件,找到对其感兴趣的监听器,触发监听器的执行)
/**
* 简单的事件广播器
*
* @author yangyongjie
*/
public class SimpleEventMulticaster implements EventMulticaster {
private static volatile SimpleEventMulticaster simpleEventMulticaster;
private SimpleEventMulticaster() {
}
/**
* 双重检查单例模式
* @return
*/
public static SimpleEventMulticaster getInstance() {
if (simpleEventMulticaster == null) {
synchronized (SimpleEventMulticaster.class) {
if (simpleEventMulticaster == null) {
simpleEventMulticaster = new SimpleEventMulticaster();
}
}
}
return simpleEventMulticaster;
}
private static final Set<Listener<?>> LISTENERS = new LinkedHashSet<>();
static {
ServiceLoader<Listener> loadListeners = ServiceLoader.load(Listener.class);
Iterator<Listener> litenersIterator = loadListeners.iterator();
try {
while (litenersIterator.hasNext()) {
Listener listener = litenersIterator.next();
LISTENERS.add(listener);
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void addListener(Listener<?> listener) {
LISTENERS.add(listener);
}
@Override
public void removeListener(Listener<?> listener) {
LISTENERS.remove(listener);
}
@Override
public void multicastEvent(Event<?> event) {
multicastEvent(event, true);
}
@Override
public void multicastEvent(Event<?> event, boolean async) {
multicastEvent(event, async, 0L);
}
@Override
public void multicastEvent(Event<?> event, boolean async, long delayMillis) {
Class<?> eventClass = event.getClass();
Set<Listener<?>> interestedListeners = getInterestedListeners(eventClass);
// 事件发生,异步调用监听器的事件方法
for (Listener<?> listener : interestedListeners) {
if (async) {
ListenerExecutor.execute(() -> {
// 调用监听器的执行
invokeListener(listener, event, delayMillis);
});
} else {
// 调用监听器的执行
invokeListener(listener, event, delayMillis);
}
}
}
/**
* 调用监听器执行
*
* @param listener
* @param event
*/
private void invokeListener(Listener listener, Event<?> event, long delayMillis) {
try {
// 如果延迟时间不为0,则睡眠等待
if (delayMillis != 0) {
Thread.sleep(delayMillis);
}
listener.onEvent(event);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取对当前事件感兴趣的监听器(监听了当前事件或当前事件的父事件)
*
* @param eventClass
*/
private Set<Listener<?>> getInterestedListeners(Class<?> eventClass) {
// 存放监听对发布事件感兴趣的监听器
Set<Listener<?>> interestedListeners = new LinkedHashSet<>();
for (Listener<?> listener : LISTENERS) {
// 获取监听器的泛型类型(即监听器监听的事件类型)
Class<?> genericClass = getGeneric(listener.getClass(), Listener.class);
if (genericClass == null) {
return interestedListeners;
}
// 监听器监听的事件类型是否是发布事件类型的父类 或与发布的事件类型相同
boolean interested = genericClass.isAssignableFrom(eventClass);
if (interested) {
interestedListeners.add(listener);
}
}
return interestedListeners;
}
private Class<?> getGeneric(Class<?> clazz, Class<?> intfClass) {
if (intfClass != null) {
Type[] genericIfcs = clazz.getGenericInterfaces();
for (Type type : genericIfcs) {
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
Type rawType = parameterizedType.getRawType();
Class<?> rawTypeClass = rawType instanceof Class ? (Class<?>) rawType : null;
if (rawTypeClass == null || !rawTypeClass.isAssignableFrom(intfClass)) {
continue;
}
return resolveType(type);
}
}
} else {
// 返回表示这个类所表示的实体(类、接口、基本类型或void)的直接超类的类型,如果超类是参数化类型,则返回的type对象必须准确反映源代码中使用的实际类型参数
Type type = clazz.getGenericSuperclass();
return resolveType(type);
}
return null;
}
private Class<?> resolveType(Type type) {
Class<?>[] generics;
if (type instanceof ParameterizedType) {
// 获取到父类/父接口的泛型数组
Type[] actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
int length = actualTypeArguments.length;
generics = new Class<?>[length];
// 获取泛型
for (int i = 0; i < actualTypeArguments.length; i++) {
Type actualType = actualTypeArguments[i];
if (actualType instanceof Class) {
generics[i] = (Class<?>) actualType;
}
}
return (generics.length == 0 ? null : generics[0]);
}
return null;
}
}
6、监听器执行线程池
/**
* 监听器执行线程池
*
* @author yangyongjie
*/
public final class ListenerExecutor {
private ListenerExecutor() {
}
/**
* cpu核心数
*/
private static final int CPU_CORE = Runtime.getRuntime().availableProcessors();
/**
* 核心线程数
*/
private static final int HYPER_THREAD = CPU_CORE * 2;
/**
* 线程池
*/
private static final ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(
CPU_CORE,
HYPER_THREAD,
60,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(10000),
new CustomThreadFactory("listenerExecutor"),
(r, executor) -> {
// 打印日志
// 直接执行被拒绝的任务,JVM另起线程执行
r.run();
}
);
/**
* 提交线程池处理
*
* @param runnable 任务
*/
protected static void execute(Runnable runnable) {
EXECUTOR.execute(runnable);
}
/**
* 提交线程池处理任务,可获取返回值
*
* @param callable 任务
* @param <T> 返回值类型
* @return Future
*/
protected static <T> Future<T> submit(Callable<T> callable) {
return EXECUTOR.submit(callable);
}
/**
* 创建线程的工厂,指定有意义的线程组名称,方便回溯
*
* @author yangyongjie
*/
public static class CustomThreadFactory implements ThreadFactory {
/**
* 线程池中的线程名称前缀
*/
private final String namePrefix;
/**
* 用于线程的名称递增排序
*/
private final AtomicInteger atomicInteger = new AtomicInteger(1);
public CustomThreadFactory(String whatFeatureOfGroup) {
this.namePrefix = "From CustomThreadFactory-" + whatFeatureOfGroup + "-worker-";
}
@Override
public Thread newThread(Runnable r) {
String name = namePrefix + atomicInteger.getAndIncrement();
return new Thread(r, name);
}
}
}
使用:
EventCaster.multicastEvent(new DemoEvent(new HashMap<>()));
注意:在toC的项目中禁止使用延时发布事件(事件发布后延时执行),采用sleep方式,会造成线程池任务堆积,从而执行拒绝策略,同时等待队列中任务排队等待时间过长,造成任务执行的积压
END.