异步管理器
如果系统每一步的日志记录都是伴随着业务一起执行的,那么当系统访问量增加的时候,就会大大降低系统的响应速度。这时我们就可以使用异步管理器去保存日志信息。
创建异步管理器
public class AsyncManager {
/**
* 操作延迟10毫秒
*/
private final int OPERATE_DELAY_TIME = 10;
/**
* 异步操作任务调度线程池
*/
private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService");
/**
* 单例模式
*/
private AsyncManager() {
}
private static AsyncManager me = new AsyncManager();
public static AsyncManager me() {
return me;
}
/**
* 执行任务
*
* @param task 任务
*/
public void execute(TimerTask task) {
executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);
}
/**
* 停止任务线程池
*/
public void shutdown() {
Threads.shutdownAndAwaitTermination(executor);
}
}
通过 SpringUtils.getBean("scheduledExecutorService") 从Spring 中获取 scheduledExecutorService,这个 Bean 用来创建一个调度线程池执行器。
线程池配置
@Configuration
public class ThreadPoolConfig {
// 核心线程池大小
private int corePoolSize = 50;
// 最大可创建的线程数
private int maxPoolSize = 200;
// 队列最大长度
private int queueCapacity = 1000;
// 线程池维护线程所允许的空闲时间
private int keepAliveSeconds = 300;
@Bean(name = "threadPoolTaskExecutor")
public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setMaxPoolSize(maxPoolSize);
executor.setCorePoolSize(corePoolSize);
executor.setQueueCapacity(queueCapacity);
executor.setKeepAliveSeconds(keepAliveSeconds);
// 线程池对拒绝任务(无线程可用)的处理策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
return executor;
}
/**
* 执行周期性或定时任务
*/
@Bean(name = "scheduledExecutorService")
protected ScheduledExecutorService scheduledExecutorService() {
return new ScheduledThreadPoolExecutor(corePoolSize,
new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build()) {
@Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
Threads.printException(r, t);
}
};
}
}
threadPoolTaskExecutor 初始化 ThreadPoolTaskExecutor 线程池任务执行器
scheduledExecutorService Bean 实例是用来创建一个调度线程池执行器,并需重写 afterExecute() 方法,去处理执行任务过程中产生的异常或执行完成后的下一步操作流程,主要是用于 执行周期性或定时任务 ,后面会用到它去异步执行记录登录日志任务。
异步任务工厂
设计这个类主要是用来产生 TimerTask 的,比如用户访问登录页面,登录判断的同时,还需记录下用户登录的日志情况,是登录成功了呢?还是失败了!退出登录也可以记录到日志表中,并且完全不用担心后端处理不过来的问题,因为它是放在异步操作任务调度线程池当中。
这个类是生产 TimerTask ,所以直接 new 一个 TimerTask 返回就可以了,至于里面的操作,就要看实际业务了。
public class AsyncFactory {
private static final Logger sys_user_logger = LoggerFactory.getLogger("sys-user");
/**
* 操作日志记录
*
* @param operLog 操作日志信息
* @return 任务task
*/
public static TimerTask recordOper(final SysOperLog operLog) {
return new TimerTask() {
@Override
public void run() {
// 远程查询操作地点
operLog.setOperLocation("xxx");
SpringUtils.getBean(ISysOperLogService.class).insertOperlog(operLog);
}
};
}
}