自定义线程池的配置类 AsyncConfig
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.ThreadPoolExecutor;
@Configuration
@EnableAsync
/**
* @Description: 自定义线程池的配置类,并在类上添加@EnableAsync 注解,
* 然后在需要异步的方法上使用@Async("线程池名称") 该方法就可以异步执行了
* @Param: * @param null
* @return:
* @Author: wenliang
* @Date: 2019/11/6
**/
public class AsyncConfig {
private static final Logger logger = LoggerFactory.getLogger(AsyncConfig.class);
@Bean("taskExecutor") // bean的名称,,不写的里面值,则默认为首字母小写的方法名
public TaskExecutor taskExecutor() {
logger.info("start asyncServiceExecutor");
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
int core = Runtime.getRuntime().availableProcessors();
//配置核心线程数
executor.setCorePoolSize(core);
//配置最大线程数
executor.setMaxPoolSize(core * 2 + 1);
// 允许线程空闲时间(单位:默认为秒)
executor.setKeepAliveSeconds(5);
//配置队列大小
executor.setQueueCapacity(9999);
//配置线程池中的线程的名称前缀
executor.setThreadNamePrefix("async-service-");
// rejection-policy:当pool已经达到max size的时候,如何处理新任务
// CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setWaitForTasksToCompleteOnShutdown(true);
//执行初始化
executor.initialize();
return executor;
}
}
注① @Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。
注② @EnableAsync开始对异步任务的支持
接着写个service类 testAsyncService :
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@Service
public class testAsyncService {
Logger log = LoggerFactory.getLogger(testAsyncService.class);
// 发送提醒短信 1
@Async("taskExecutor")
public void service1() throws InterruptedException {
log.info("--------start-service1------------");
Thread.sleep(5000); // 模拟耗时
log.info("--------end-service1------------");
}
// 发送提醒短信 2
@Async("taskExecutor")
public void service2() throws InterruptedException {
log.info("--------start-service2------------");
Thread.sleep(2000); // 模拟耗时
log.info("--------end-service2------------");
}
注① 使用@Async注解来声明一个或多个异步任务,可以加在方法或者类上,加在类上表示这整个类都是使用这个自定义线程池进行操作
接着我们可以创建control类@Autowired这个service并且调用这其中两个方法,进行连续调用,会发现运行结果是
--------start-service1------------
--------start-service2------------
--------end-service2------------
--------end-service1------------
可以说明我们的异步运行成功了
注意点:
一、异步方法使用static修饰
二、异步类没有使用@Component注解(或其他注解)导致spring无法扫描到异步类
三、类中需要使用@Autowired或@Resource等注解自动注入,不能自己手动new对象
五、如果使用SpringBoot框架必须在启动类中增加@EnableAsync注解