Spring开启方法异步执行

Posted 如若

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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
@EnableAsync
public class AppConfig implements AsyncConfigurer {

    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(7);
        executor.setMaxPoolSize(42);
        executor.setQueueCapacity(11);
        executor.setThreadNamePrefix("MyExecutor-");
        executor.initialize();
        return executor;
    }

    @Override
    public 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 {

   @Async
   public void task1() {
       try {
           Thread.sleep(3000);
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
   }

   @Async
   public 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);

   @Autowired
   private AsyncTask asyncTask;

   @Test
   public void testTask1(){
       log.info("start");
       asyncTask.task1();
       log.info("finish");
   }

   @Test
   public 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事务注解在同一个方法上同时使用,不然事务注解将无效。

要使用事务,需要把事务注解提取到方法里面的子方法上。

以上是关于Spring开启方法异步执行的主要内容,如果未能解决你的问题,请参考以下文章

Springboot 使用@Async开启异步调用

Spring多线程

Spring Boot 中的异步调用

Spring中@Async注解实现“方法”的异步调用

spring异步方法@Async

springboot 多线程执行