springboot线程池
大约 2 分钟javaspring
APP开启多线程
在 ShowApplication.java 启动类头上添加下面两个注解,注意类 EmailThreadPoolConfig 指定了读取项目配置文件参数并创建 bean 对象到 app 中
@EnableAsync
@EnableConfigurationProperties({EmailThreadPoolConfig.class} ) // 开启配置属性支持
线程池配置文件
threadpool:
email:
corePoolSize: 20
maxPoolSize: 40
keepAliveSeconds: 300
queueCapacity: 50
配置文件类
package com.xdf.showa.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* @author chanchaw
* @create 2023-06-22 16:37
*/
@ConfigurationProperties(prefix = "threadpool.email")
public class EmailThreadPoolConfig {
private int corePoolSize;
private int maxPoolSize;
private int keepAliveSeconds;
private int queueCapacity;
public int getCorePoolSize() {
return corePoolSize;
}
public void setCorePoolSize(int corePoolSize) {
this.corePoolSize = corePoolSize;
}
public int getMaxPoolSize() {
return maxPoolSize;
}
public void setMaxPoolSize(int maxPoolSize) {
this.maxPoolSize = maxPoolSize;
}
public int getKeepAliveSeconds() {
return keepAliveSeconds;
}
public void setKeepAliveSeconds(int keepAliveSeconds) {
this.keepAliveSeconds = keepAliveSeconds;
}
public int getQueueCapacity() {
return queueCapacity;
}
public void setQueueCapacity(int queueCapacity) {
this.queueCapacity = queueCapacity;
}
@Override
public String toString() {
return "EmailThreadPoolConfig{" +
"corePoolSize=" + corePoolSize +
", maxPoolSize=" + maxPoolSize +
", keepAliveSeconds=" + keepAliveSeconds +
", queueCapacity=" + queueCapacity +
'}';
}
}
线程池类
package com.xdf.showa.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
/**
* @author chanchaw
* @create 2023-06-22 16:39
*/
@Configuration
@EnableAsync
public class EmailThreadPool {
@Autowired
private EmailThreadPoolConfig config;
@Bean
public Executor ccEmailThreadPool() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//核心线程池大小
executor.setCorePoolSize(config.getCorePoolSize());
//最大线程数
executor.setMaxPoolSize(config.getMaxPoolSize());
//队列容量
executor.setQueueCapacity(config.getQueueCapacity());
//活跃时间
executor.setKeepAliveSeconds(config.getKeepAliveSeconds());
//线程名字前缀
executor.setThreadNamePrefix("ccEmailThread-");
// setRejectedExecutionHandler:当pool已经达到max size的时候,如何处理新任务
// CallerRunsPolicy:不在新线程中执行任务,而是由调用者所在的线程来执行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
}
用于测试的业务功能
package com.xdf.showa.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
/**
* @author chanchaw
* @create 2023-06-22 16:42
*/
@Slf4j
@Component
public class AsyncTask {
@Async("ccEmailThreadPool") //ccEmailThreadPool即配置线程池的方法名,此处如果不写自定义线程池的方法名,会使用默认的线程池
public void doTask1(int i) throws InterruptedException{
log.info("Task"+i+" started.");
}
}
测试
在任意 bean 的类中自动注入业务逻辑类 AsyncTask 并通过循环调用多个任务测试是否使用了多线程,注意看日志文件。软件中发送邮件会比较耗时,要采用线程池的方式发送邮件
@Autowired
private AsyncTask asyncTask;
@PostConstruct
public void testEmailThreadPool() throws InterruptedException {
log.info("开始线程池任务");
for(int i=0;i<20;i++){
asyncTask.doTask1(i);
}
log.info("线程池任务结束");
}
