天天看點

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事務注解在同一個方法上同時使用,不然事務注解将無效。

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

歡迎大家轉發到朋友圈,和朋友們一起提升自己。