一、线程池的创建方式
方式(一):通过构造函数ThreadPoolExecutor()方式创建线程池
步骤1:先构建线程池
public class AsyncTaskExecutor {
/**
* 核心线程数
*/
private static final int corePoolSize = 10;
/**
* 最大线程数
*/
private static final int maxPoolSize = 30;
/**
* 空闲线程回收时间
* 空闲线程是指:当前线程池中超过了核心线程数之后,多余的空闲线程的数量
*/
private static final int keepAliveTime = 100;
/**
* 任务队列/阻塞队列
*/
private static final int blockingQueueSize = 99999;
private static final ThreadPoolExecutor executorPool = new ThreadPoolExecutor(
corePoolSize,
maxPoolSize,
keepAliveTime,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(blockingQueueSize),
new ThreadFactoryBuilder().setNameFormat("AsyncTaskThread" + "-%d").build(),
new ThreadPoolExecutor.CallerRunsPolicy()
);
/**
* 异步任务执行
*
* @param task
*/
public static void execute(Runnable task) {
executorPool.execute(task);
}
}
步骤2:通过实现Runnable接口,创建异步任务
@Slf4j
public class CommonTask implements Runnable {
/**
* 模块ID
*/
private Long modelId;
/**
* 模块名称
*/
private ModelEnum modelName;
/**
* 构造方法
*
* @param modelId
* @param modelName
*/
public CommonTask(Long modelId, ModelEnum modelName) {
this.modelId = modelId;
this.modelName = modelName;
}
@Override
public void run() {
log.info("start to process common task!!!");
if (modelId.intValue() == ModelEnum.Chinese.getCode()) {
String name = ModelEnum.Chinese.getValue();
log.info("modelID = {} modelName = {}", modelId, name);
} else {
modelName = ModelEnum.forValue(modelId.intValue());
log.info("modelID = {} modelName = {}", modelId, modelName.getValue());
}
}
}
枚举
public enum ModelEnum {
Chinese(1, "语文"),
Math(2, "数学"),
English(3, "数学");
/**
* code
*/
private int code;
/**
* value
*/
private String value;
/**
* 映射结果集
*/
private static final Map<Integer, ModelEnum> VALUE_MAP;
static {
VALUE_MAP = new HashMap<>();
for (ModelEnum modelEnum : ModelEnum.values()) {
VALUE_MAP.put(modelEnum.code, modelEnum);
}
}
ModelEnum(int code, String value) {
this.code = code;
this.value = value;
}
public int getCode() {
return code;
}
public String getValue() {
return value;
}
/**
* 根据code获取枚举实例
*
* @param code
* @return
*/
public static ModelEnum forValue(int code) {
return VALUE_MAP.get(code);
}
}
步骤3:验证
//步骤1:创建异步任务
CommonTask task = new CommonTask(1L, ModelEnum.Chinese);
//步骤2:调用线程池异步执行任务
AsyncTaskExecutor.execute(task);
log.info("main thread over...");
结果如下:
2024-05-23 14:53:16.096 INFO 20652 --- [ main] com.example.demo.dao.UserDaoTest : main thread over...
2024-05-23 14:53:16.097 INFO 20652 --- [yncTaskThread-0] com.example.demo.task.CommonTask : start to process common task!!!
2024-05-23 14:53:16.097 INFO 20652 --- [yncTaskThread-0] com.example.demo.task.CommonTask : modelID = 1 modelName = 语文
方式(二):构建ThreadPoolTaskExecutor线程池,将其声明为Bean,可以通过注入bean的方式和在方法上使用@Async(“asyncTaskExecutor”)这种注解方式使用此线程池
@Slf4j
@Configuration
@EnableAsync
public class TaskExecutor {
@Value("${async.executor.thread.core_pool_size}")
private int corePoolSize;
@Value("${async.executor.thread.max_pool_size}")
private int maxPoolSize;
@Value("${async.executor.thread.queue_capacity}")
private int queueCapacity;
@Value("${async.executor.thread.name.deal_task}")
private String taskNamePrefix;
/**
* 构建线程池 并将其声明为Bean
* 方式1:可以通过注入的方式使用此线程池
* 方式2:可以在方法上使用@Async("asyncTaskExecutor")这种注解方式使用此线程池
*
* @return
*/
@Bean(name = "asyncTaskExecutor")
public Executor asyncTaskExecutor() {
log.info("start asyncTaskExecutor...");
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
threadPoolTaskExecutor.setCorePoolSize(corePoolSize);
threadPoolTaskExecutor.setMaxPoolSize(maxPoolSize);
threadPoolTaskExecutor.setQueueCapacity(queueCapacity);
threadPoolTaskExecutor.setThreadNamePrefix(taskNamePrefix);
//拒绝策略:当前线程数已经达到最大线程数后,如何处理新任务
//CallerRunsPolicy()不在新线程中执行任务,而是返回调用者所在的线程来执行
threadPoolTaskExecutor.setRejectedExecutionHandler(
new ThreadPoolExecutor.CallerRunsPolicy());
threadPoolTaskExecutor.initialize();
return threadPoolTaskExecutor;
}
}
在application.yml中的配置
async:
executor:
thread:
core_pool_size: 10
max_pool_size: 10
queue_capacity: 99999
name:
deal_task: DEAL-TASK-
使用方式1:在方法上使用@Async(“asyncTaskExecutor”)这种注解方式使用此线程池
使用方式2:通过注入的方式使用此线程池
@Slf4j
@Service
public class WorkServiceImpl implements WorkService {
@Async("asyncTaskExecutor")
public void doAsyncTask() throws InterruptedException {
Thread.sleep(1000);
log.info("do AsyncTask...");
}
}
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserDaoTest {
SqlSession sqlSession;
@Resource
private WorkService workService;
@Resource
private Executor asyncTaskExecutor;
@Test
public void test() {
try {
//方式1:在方法上使用@Async("asyncTaskExecutor")这种注解方式使用此线程池
for (int i = 0; i < 5; i++) {
workService.doAsyncTask();
}
log.info("main Thread over...");
//方式2:通过注入的方式使用此线程池(方便)
asyncTaskExecutor.execute(() -> {
log.info("async task is running..");
});
Thread.sleep(5000);
}catch (Exception e) {
e.printStackTrace();
}
}
}