持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第30天,点击查看活动详情
异步在项目中用到的很多
为什么要配置异步线程池,默认的线程池并不会去复用线程,所以我们需要配置线程池参数从而使得异步任务更高效的执行。
下面我们就来配置一下
具体的线程池参数 大家可以看看我之前写的另一篇 springboot CompletableFuture异步线程池 这里就不多讲啦..........😁
@Configuration
@EnableAsync
public class ThreadPoolConfig
{
// 核心线程池大小
private int corePoolSize = 5;
// 最大可创建的线程数
private int maxPoolSize = 10;
// 队列最大长度
private int queueCapacity = 20;
// 线程池维护线程所允许的空闲时间
private int keepAliveSeconds = 300;
@Bean(name = "threadPoolExecutor")
public Executor threadPoolExecutor(){
ThreadPoolTaskExecutor executor =new ThreadPoolTaskExecutor();
executor.setCorePoolSize(corePoolSize);//核心池大小
executor.setMaxPoolSize(maxPoolSize);//最大线程数
executor.setQueueCapacity(queueCapacity);//队列长度 不设置为无边界
executor.setKeepAliveSeconds(keepAliveSeconds);//线程空闲时间
executor.setThreadNamePrefix("bugVip-asyn");//线程前缀名称
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());//配置拒绝
executor.initialize();
return executor;
}
}
项目中使用
@Async("threadPoolExecutor")
public void loginLogSet(String username, String description, Integer logType, Integer runType, Integer whereType, String message) throws InterruptedException {
}
控制台打印
@Async("threadPoolExecutor")里面指定使用的线程池,因为我们可以配置多个线程池前提是你的硬件跟的上哈哈,一般就是两个池子核心业务和一般业务(日志记录呀等等)。
还可以使用Aop 做一个获取线程池子的执行状态的注解
注解 @ThreadPoolStatus这里就不多少怎么创建了
@RequestMapping("info")
@ThreadPoolStatus("info-------------------------------------->")
public R info(HttpServletRequest request){
String tokeninfo = tokenManager.getUserToken(request.getHeader(header));
OnlineUserInfo principal = redisTemplate.getCacheObject(RedisConstant.ONLINE_BOSS_INFO + tokeninfo);
SysUser sysUser = principal.getSysUser();
return R.ok().data("user",sysUser);
}
Aop的代码
@Slf4j
@Aspect
@Component
public class TheadPoolLogAop {
@Resource(name = "threadPoolExecutor")
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
@Pointcut("@annotation(com.xk.bugvip.boss.log.ThreadPoolStatus)")
public void threadPoolStatus(){}
private static HashMap<String, Class> map = new HashMap<String, Class>() {
{
put("java.lang.Integer", int.class);
put("java.lang.Double", double.class);
put("java.lang.Float", float.class);
put("java.lang.Long", long.class);
put("java.lang.Short", short.class);
put("java.lang.Boolean", boolean.class);
put("java.lang.Char", char.class);
put("javax.servlet.http.HttpServletRequest", HttpServletRequest.class);
}
};
@Around("threadPoolStatus()")
public Object threadPoolDoing(ProceedingJoinPoint point) throws Throwable {
Object target = point.getTarget();
Class<?> aClass = target.getClass();
String name = aClass.getName();
String methodName = point.getSignature().getName();
Object[] args = point.getArgs();
Class<?>[] classes = new Class[args.length];
for (int k = 0; k < args.length; k++) {
if (!args[k].getClass().isPrimitive()) {
//获取的是封装类型而不是基础类型
String result = args[k].getClass().getName();
Class s = map.get(result);
classes[k] = s == null ? args[k].getClass() : s;
}
}
//获取指定的方法,第二个参数可以不传,但是为了防止有重载的现象,还是需要传入参数的类型
Class<?> aClass1 = Class.forName(name);
try {
MethodSignature methodSignature = (MethodSignature)point.getSignature();
ThreadPoolStatus annotation = methodSignature.getMethod().getAnnotation(ThreadPoolStatus.class);
showThreadPoolInfo(annotation.value());
return point.proceed();
}catch (Exception e){
log.info(e.getMessage());
}
return null;
}
private void showThreadPoolInfo(String prefix){
ThreadPoolExecutor threadPoolExecutor = threadPoolTaskExecutor.getThreadPoolExecutor();
if(null==threadPoolExecutor){
return;
}
log.info("{}, {},taskCount [{}], completedTaskCount [{}], activeCount [{}],PoolSize[{}],LargestPoolSize[{}], queueSize [{}]",
threadPoolTaskExecutor.getThreadNamePrefix(),
prefix,
threadPoolExecutor.getTaskCount(),//线程需要执行的任务个数。
threadPoolExecutor.getCompletedTaskCount(),//线程池在运行过程中已完成的任务数。
threadPoolExecutor.getActiveCount(),//获取活动的线程的数量。
threadPoolExecutor.getPoolSize(),//当前相乘数量
threadPoolExecutor.getLargestPoolSize(),//线程池曾经创建过的最大线程数量。
threadPoolExecutor.getQueue().size());//任务队列中任务数量
}
}
输出结果
这个功能可能有点鸡肋,但是也是可以用的。感兴趣的可以去试试........
实践是检验真理的唯一方法! 明天见🥰🥰🥰