持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第26天,点击查看活动详情
package com.yitiao.async;
import com.yitiao.entity.CommerceGoods;
import com.yitiao.enums.AsyncTaskStatusEnum;
import com.yitiao.vo.AsyncTaskInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.*;
@Slf4j
@Component
public class AsyncTaskManager {
/** 异步任务执行信息容器 */
private final Map<String, AsyncTaskInfo> taskContainer =
new HashMap<>(16);
private final AsyncService asyncService;
public AsyncTaskManager(AsyncService asyncService) {
this.asyncService = asyncService;
}
/**
* <h2>初始化异步任务</h2>
* */
public AsyncTaskInfo initTask() {
AsyncTaskInfo taskInfo = new AsyncTaskInfo();
// 设置一个唯一的异步任务 id, 只要唯一即可
taskInfo.setTaskId(UUID.randomUUID().toString());
taskInfo.setStatus(AsyncTaskStatusEnum.STARTED);
taskInfo.setStartTime(new Date());
// 初始化的时候就要把异步任务执行信息放入到存储容器中
taskContainer.put(taskInfo.getTaskId(), taskInfo);
return taskInfo;
}
/**
* <h2>提交异步任务</h2>
* */
public AsyncTaskInfo submit(List<CommerceGoods> goodsInfos) {
// 初始化一个异步任务的监控信息
AsyncTaskInfo taskInfo = initTask();
asyncService.asyncImportGoods(goodsInfos, taskInfo.getTaskId());
return taskInfo;
}
/**
* <h2>设置异步任务执行状态信息</h2>
* */
public void setTaskInfo(AsyncTaskInfo taskInfo) {
taskContainer.put(taskInfo.getTaskId(), taskInfo);
}
/**
* <h2>获取异步任务执行状态信息</h2>
* */
public AsyncTaskInfo getTaskInfo(String taskId) {
return taskContainer.get(taskId);
}
}
线程池配置
package com.yitiao.config;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.lang.reflect.Method;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
@Slf4j
@EnableAsync // 开启 Spring 异步任务支持
@Configuration
public class AsyncPoolConfig implements AsyncConfigurer {
@Bean
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(20);
executor.setQueueCapacity(20);
executor.setKeepAliveSeconds(60);
executor.setThreadNamePrefix("Qinyi-Async-"); // 这个非常重要
// 等待所有任务结果候再关闭线程池
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setAwaitTerminationSeconds(60);
// 定义拒绝策略
executor.setRejectedExecutionHandler(
new ThreadPoolExecutor.CallerRunsPolicy()
);
// 初始化线程池, 初始化 core 线程
executor.initialize();
return executor;
}
/**
* <h2>指定系统中的异步任务在出现异常时使用到的处理器</h2>
* */
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new AsyncExceptionHandler();
}
/**
* <h2>异步任务异常捕获处理器</h2>
* */
@SuppressWarnings("all")
class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
@Override
public void handleUncaughtException(Throwable throwable, Method method,
Object... objects) {
throwable.printStackTrace();
log.error("Async Error: [{}], Method: [{}], Param: [{}]",
throwable.getMessage(), method.getName(),
JSON.toJSONString(objects));
// TODO 发送邮件或者是短信, 做进一步的报警处理
}
}
}