@Async注解
我们都知道使用@Async标注在方法上,可以使该方法异步的调用执行。而所有异步方法的实际执行是交给TaskExecutor的。
关于@Async的基本知识不做讲解,只是对于使用过程中需要的注意的点做下强调
废话不多数,直接上使用
1.启动类上添加@EnableAsync注解
/** * 小程序启动类 */ @EnableAsync @SpringBootApplication(exclude= {DataSourceAutoConfiguration.class}) public class SmallProgramApplication { public static void main(String[] args) { SpringApplication.run(SmallProgramApplication.class, args); } }
2.方法上添加@Async,类上添加@Component
1.controller
/** * 异步测试方法 * @throws InterruptedException */ @GetMapping("/sync") private void sync() throws InterruptedException { testService.sync(); }2.service
/** * 异步-测试方法 */ void sync() throws InterruptedException;3.impl
@Autowired public SyncUtils syncUtils; /** * 异步测试方法 */ @Override public void sync() throws InterruptedException { long begin = System.currentTimeMillis(); for (int i = 1; i <= 50; i++) { System.out.println("第" + i + "次調用"); syncUtils.sync1(); syncUtils.sync2(); syncUtils.sync3(); } long timeValue = System.currentTimeMillis() - begin; System.out.println("耗时:" + timeValue + "毫秒"); }4.单独的类
package com.aty.basissmallprogram.utlis; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; @Service public class SyncUtils { @Async public void sync1() throws InterruptedException { Thread.sleep(5000); } @Async public void sync2() throws InterruptedException { Thread.sleep(5000); } @Async public void sync3() throws InterruptedException { Thread.sleep(5000); } }注意:1.不要本类调本类,会导致失效
2. @Async可以打在类上,即所有方法默认是异步方法
3.设置线程池
注意为什么需要线程池:这是因为在我们不指定线程池的情况下,spring默认使用SimpleAsyncTaskExecutor。该线程池默认来一个任务创建一个线程。当异步任务非常多时,后果不堪设想。。。。
package com.aty.basissmallprogram.config; import lombok.extern.slf4j.Slf4j; import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.AsyncConfigurer; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import java.util.concurrent.Executor; import java.util.concurrent.ThreadPoolExecutor; /** * @Description 异步线程池配置 * @Author wy * @Date 2022-01-04 */ @Slf4j @EnableAsync @Configuration public class AsyncConfiguration implements AsyncConfigurer { @Bean("asyncExecutor") public Executor executor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(4); //核心线程数 executor.setMaxPoolSize(8); //最大线程数 executor.setQueueCapacity(200); //队列大小 executor.setThreadNamePrefix("async_executor_default_"); //指定用于新创建的线程名称的前缀。 // 设置拒绝策略:当pool已经达到max size的时候,如何处理新任务 // CALLER_RUNS:不在新线程中执行任务,而是由调用者所在的线程来执行 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 拒绝策略 executor.setWaitForTasksToCompleteOnShutdown(true); //等待任务在关机时完成--表明等待所有线程执行完 executor.setAwaitTerminationSeconds(10); // 等待时间 (默认为0,此时立即停止),并没等待xx秒后强制停止 executor.initialize(); // 初始化 return executor; } @Override public Executor getAsyncExecutor() { return executor(); } @Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { return (ex, method, params) -> { log.error("Async Exception***********************************************"); log.error("method happen: {}", method); log.error("method params: {}", params); log.error("Exception class: {}", ex.getClass().getName()); log.error("ex.getMessage(): {}", ex.getMessage()); log.error("**************************************************************"); }; } }