1. 自定义Spring线程池使用
business_demo业务工程依赖下面的common_web工程(jar工程)。
DemoApplication中使用@EnableAsync启动异步。
package com.ken.business.demo.application;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
@SpringBootApplication
@EnableAsync
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
StudentServiceImpl类中方法上加上@Async注解。
package com.ken.business.demo.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ken.business.demo.service.StudentService;
import com.ken.data.entity.demo.Student;
import com.ken.data.mapper.demo.dao.StudentDao;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class StudentServiceImpl extends ServiceImpl<StudentDao, Student> implements StudentService {
@Async
@Override
public List<Student> list() {
System.out.println("当前线程:" + Thread.currentThread().getName());
return super.list();
}
}
2. 自定义Spring线程池实现
在common_web工程中实现自定义Spring线程池。
2.1 AsyncExecutorConfig
package com.ken.common.web.async;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
/**
* 自定义的异步线程池
*/
@Configuration
@Slf4j
public class AsyncExecutorConfig {
@Autowired
private AsyncExecurityConfiguration asyncExecurityConfiguration;
/**
* 自定义线程池参数
* @return
*/
@Bean
@Primary
@ConditionalOnBean(annotation = EnableAsync.class) // 如果业务工程中DemoApplication启动类上没有加@EnableAysnc注解,这个自定义的Spring线程池也不要加载
public Executor getAsyncExecutor(){
log.debug("[Async-Executor-init] - 线程池初始化 - {}", asyncExecurityConfiguration);
//创建线程池包装对象
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
//设置线程池参数
taskExecutor.setCorePoolSize(asyncExecurityConfiguration.getCoreNum());//核心线程数
taskExecutor.setMaxPoolSize(asyncExecurityConfiguration.getMaxNum());//最大线程数
taskExecutor.setKeepAliveSeconds(asyncExecurityConfiguration.getMaxTimeoutSec());//空闲线程的最大存活时间
taskExecutor.setAllowCoreThreadTimeOut(asyncExecurityConfiguration.isAllowCoreThreadTimeOut());//是否允许核心线程超时
taskExecutor.setRejectedExecutionHandler(asyncExecurityConfiguration.getRejectHandler().getRejectedExecutionHandler());//设置拒绝策略
taskExecutor.setThreadNamePrefix(asyncExecurityConfiguration.getThreadNamePrefix());//设置线程名称的前缀
taskExecutor.setQueueCapacity(asyncExecurityConfiguration.getQueueCapacity());//阻塞队列的最大容量
taskExecutor.initialize();
return taskExecutor;
}
}
2.2 AsyncExecurityConfiguration
package com.ken.common.web.async;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import javax.annotation.PostConstruct;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
@ConfigurationProperties(prefix = "async.executor")
@Data
public class AsyncExecurityConfiguration {
/**
* 核心线程数
*/
private Integer coreNum;
/**
* 最大线程数
*/
private Integer maxNum;
/**
* 最大空闲时间
*/
private Integer maxTimeoutSec = 300;
/**
* 是否允许核心线程数超时
*/
private boolean allowCoreThreadTimeOut = false;
/**
* 线程名称的前缀
*/
private String threadNamePrefix = "Ken-Executor-";
/**
* 阻塞队列的最大容量
*/
private Integer queueCapacity = 1000;
/**
* 线程拒绝的方式
*/
private RejectEunm rejectHandler = RejectEunm.CallerRunsPolicy;
@PostConstruct
public void init(){
//获得cpu的核心数量
int core = Runtime.getRuntime().availableProcessors();
//配置核心线程数 - cpu核心数 - CPU密集型的应用
if (coreNum == null || coreNum <= 0) {
coreNum = core;
}
//配置最大线程数 - cpu核心数 * 2 - IO密集型的应用
if (maxNum == null || maxNum <= 0) {
maxNum = core * 2;
}
}
public enum RejectEunm {
//抛出异常的方式
AbortPolicy(new ThreadPoolExecutor.AbortPolicy()),
//提交任务的线程自行执行该任务
CallerRunsPolicy(new ThreadPoolExecutor.CallerRunsPolicy()),
//线程池会放弃当前等待队列中,最久的任务,当前被拒绝的任何放入队列
DiscardOldestPolicy(new ThreadPoolExecutor.DiscardOldestPolicy()),
//直接丢弃当前拒绝的任务
DiscardPolicy(new ThreadPoolExecutor.DiscardPolicy());
/**
* 拒绝策略的处理器
*/
private RejectedExecutionHandler rejectedExecutionHandler;
RejectEunm(RejectedExecutionHandler rejectedExecutionHandler) {
this.rejectedExecutionHandler = rejectedExecutionHandler;
}
public RejectedExecutionHandler getRejectedExecutionHandler() {
return rejectedExecutionHandler;
}
}
}
2.3 WebAutoConfiguration
package com.ken.common.web.config;
import com.ken.common.web.async.AsyncExecurityConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
* Web模块的自动配置类 - SpringBoot的自动装配功能 (SpringBoot = SpringIOC + 自动装配)
*/
@Configuration
@ComponentScan("com.ken.business")
public class WebAutoConfiguration {
/**
* 线程池配套的配置类
* @return
*/
@Bean
public AsyncExecurityConfiguration getAsyncExecurityConfiguration(){
return new AsyncExecurityConfiguration();
}
}
2.4 spring.factories
com.ken.common.web.async.AsyncExecutorConfig配置在spring.factories中的目的是,业务工程启动的时候就会使用自定义的线程池替代Spring原始的线程池。
com.ken.common.web.config.WebAutoConfiguration配置在spring.factories中,业务工程引入了common_web工程后,就会加载WebAutoConfiguration类中包含的@Bean注解的类,并全都注册到Spring容器中。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.ken.common.web.config.WebAutoConfiguration,\
com.ken.common.web.async.AsyncExecutorConfig
参考的工程:https://gitee.com/wlkken/ken_framework_pom
参考课程:https://www.bilibili.com/video/BV1hQ4y1z78B?p=20