转载自 Spring开启方法异步执行
@EnableAsync
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AsyncConfigurationSelector.class)
public @interface EnableAsync {Class<? extends Annotation> annotation() default Annotation.class;boolean proxyTargetClass() default false;AdviceMode mode() default AdviceMode.PROXY;int order() default Ordered.LOWEST_PRECEDENCE;}
@EnableAsync注解即开启Spring对方法异步执行的能力,需要和注解@Configuration配合使用。
@Configuration
@EnableAsync
public class AppConfig {}
也可以自定义线程池
@Configuration@EnableAsyncpublic class AppConfig implements AsyncConfigurer {@Overridepublic Executor getAsyncExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(7);executor.setMaxPoolSize(42);executor.setQueueCapacity(11);executor.setThreadNamePrefix("MyExecutor-");executor.initialize();return executor;}@Overridepublic AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {return MyAsyncUncaughtExceptionHandler();}}
@Async
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Async {String value() default "";}
在要异步执行的方法上使用@Async注解,下面是一个没有返回值,一个带有返回值的异步调用的示例。
@Component
public class AsyncTask {@Asyncpublic void task1() {try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}}@Asyncpublic Future<String> task2() {try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}return new AsyncResult<String>("javastack"); }}
测试代码
@RunWith(SpringRunner.class)
@SpringBootTest
public class AsyncTest {private final static Logger log = LoggerFactory.getLogger(AsyncTest.class);@Autowiredprivate AsyncTask asyncTask;@Testpublic void testTask1(){log.info("start");asyncTask.task1();log.info("finish");}@Testpublic void testTask2() {log.info("start");Future<String> future = asyncTask.task2();while (true) {if (future.isDone()) {try {log.info("result is " + future.get());} catch (Exception e) {e.printStackTrace();} break;}}log.info("finish");}}
注意事项
1、使用注意
@Async只能使用到被代理的对象方法上,即代理类的入口方法处,且方法必须是public的。
2、事务处理机制
使用@Async异步注解不能和@Transaction事务注解在同一个方法上同时使用,不然事务注解将无效。
要使用事务,需要把事务注解提取到方法里面的子方法上。