技能需要反复操练
技·@Async注解
准备
springboot项目一个。
开启@Async功能
@EnableAsync // 启动类上加上此注解
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(ExperimentalApplication.class, args);
}
}
@Service
public class AsyncService {
@Async // 使用注解
public void async() {
// 在此处补充打印当前线程信息的代码
}
}
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class ApplicationTests {
@Test
void contextLoads() {
// 在你的测试单元里面测试你的service
}
}
观察控制台的打印日志并记录,此时所看到的线程信息即为@Async默认使用线程。
定义自己的线程池
1.实现AsyncConfigurer接口
org.springframework.scheduling.annotation.AsyncConfigurer
@EnableAsync // 配置在配置类上,可以将启动类上的注解去掉了
@Configuration
public class AsyncConfig implements AsyncConfigurer {
@Bean
public ThreadPoolTaskExecutor asyncExecutor() {
// spring线程池各个方法的作用自行学习,按需配置。
ThreadPoolTaskExecutor executor=new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setKeepAliveSeconds(60);
executor.setQueueCapacity(99999);
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setThreadNamePrefix("async-service-");// 看这里①
executor.setAwaitTerminationSeconds(60);
executor.setWaitForTasksToCompleteOnShutdown(true);
return executor;
}
@Override
public Executor getAsyncExecutor() {
return asyncExecutor();
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return (ex,method,params)->System.out.println(String.format("执行异步方法:%s错误,%s", params, ex)); // 在此演示中不是重点,请随意。
}
}
启动测试观察打印结果,不出意外你应该会看到和①处长得很像的东西,证明我们配置的线程池起作用了。
2.继承AsyncConfigurerSupport
org.springframework.scheduling.annotation.AsyncConfigurerSupport
将AsyncConfigurer换成AsyncConfigurerSupport即可。
3.通过ThreadPoolExecutor定义线程池
@EnableAsync
@Configuration
public class AsyncConfig {
// 这个时候需要将beanName设置为“taskExecutor”
@Bean(name=AsyncExecutionAspectSupport.DEFAULT_TASK_EXECUTOR_BEAN_NAME)
public Executor asyncExecutor1() {
return new ThreadPoolExecutor(5, 10, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(2),
new ThreadFactory() {// 自定义一个线程工厂只是为了给线程取一个我们自己的名字,别在意细节。
@Override
public Thread newThread(Runnable r) {
return new Thread(r, "async-service-" + r.hashCode());
}
});
}
}
4.通过ThreadPoolTaskExecutor创建线程池
@EnableAsync
@Configuration
public class AsyncConfig{ // 就是说实际上可以不用实现AsyncConfigurer
@Bean // 这个时候可以不指定线程名称的
public Executor asyncExecutor() {
ThreadPoolTaskExecutor executor=new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setKeepAliveSeconds(60);
executor.setQueueCapacity(99999);
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setThreadNamePrefix("async-service-");
executor.setAwaitTerminationSeconds(60);
executor.setWaitForTasksToCompleteOnShutdown(true);
return executor;
}
}
另外@Async(“线程池名称”),指定value使用自己定义的线程池。