1.开启 @Async 异步能力
添加注解 @EnableAsync ,可以放在启动类上,也可以在任意配置类上,因为我是需要配置自定义线程池,因此放在配置类上
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; //开启异步线程能力 @EnableAsync @Configuration public class AsyncConfig implements AsyncConfigurer { @Override public Executor getAsyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); // 核心线程数 executor.setCorePoolSize(10); // 最大线程数 executor.setMaxPoolSize(20); // 队列大小 executor.setQueueCapacity(1000); // 线程最大空闲时间 executor.setKeepAliveSeconds(300); // 指定用于新创建的线程名称的前缀。 executor.setThreadNamePrefix("async-cenxi-Executor-"); // 拒绝策略 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 这一步千万不能忘了,否则报错: java.lang.IllegalStateException: ThreadPoolTaskExecutor not initialized executor.initialize(); return executor; } }
2.使用
如果在同一个类中使用方法,需要先获取该方法的类的代理类,不能直接待用,如果直接调用,效果为同步操作
这里封装个获取代理类的工具类
import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; @Component public class SpringApplicationUtil implements ApplicationContextAware { private static ApplicationContext ctx = null; public SpringApplicationUtil() { } public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { if (ctx == null) { ctx = applicationContext; } } public static ApplicationContext getApplicationContext() { return ctx; } public static <T> T getBean(Class<T> requiredType) { return ctx.getBean(requiredType); } public static <T> T getBean(String name, Class<T> requiredType) { return ctx.getBean(name, requiredType); } }View Code
使用写法如下
SpringApplicationUtil.getBean(【方法的类名】.class).【需要调用的异步方法】();
例子
不在同一个类中调用方法,直接在方法上加 后 ,在需要调用的地方注入类接口
3.有个bug,子线程无法获取主线程的参数或者http请求参数,怎么办?下面可以解决
解决
在调用子线程方法之前,设置请求上下文为继承配置即可,加入下面这句指令即可。
每个主线程只需要设置一次即可,因此应该在最开头的地方设置,因此设置位置看项目具体需要
RequestContextHolder.setRequestAttributes(RequestContextHolder.getRequestAttributes(), true);
4.有个解决不了的bug
当主线程完全结束后,HttpServletRequest 获取不到数据,为null ,因此会发现有时候能获取到值,有时候为nul ,这就是谁先谁后的原因导致的
因此,对于传参,应该获取到静态值后传入异步函数中,如果仍不满足要求,那只能启用该方式了
标签:线程,java,import,org,springframework,具体,executor,Async,public From: https://www.cnblogs.com/c2g5201314/p/16719029.html