Spring Boot中@Async的作用

        在Spring中,@Async这个注解用于标记的异步的方法。方法上一旦标记了这个方法,当其它线程调用这个方法时,就会开启一个新的线程去异步处理业务逻辑。

 此注解的使用说明:

       1、此注解可以用在方法上,也可以用在类上(如果用在类上,这个类中的所有的方法就是异步的)

       2、使用此注解的方法的类对象,需要是spring管理下的bean对象

       3、程序主类或此注解的主类上,需要开启启用异步配置,配置上@EnableAsync注解

 

    以Spring boot 为例,启动类中增加@EnableAsync

@EnableAsync
@SpringBootApplication
public class ManageApplication {

}

异步类:

@Component
public class MyAsyncTask {
@Async
public void asyncCpsItemImportTask(Long platformId, String jsonList){}
}

上面的配置会启用默认的执行器,异步执行指定的方法。

在业务场景中,有时需要使用自己定义的执行器来跑异步的业务逻辑,那该怎么办呢?

上面的改造后的代码如下:

@EnableAsync
@SpringBootApplication
public class ManageApplication {

@Bean("MyExecutor")
public TaskExecutor workExecutor1(){
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
threadPoolTaskExecutor.setThreadNamePrefix("parseMyTask");
threadPoolTaskExecutor.setCorePoolSize(10);
threadPoolTaskExecutor.setMaxPoolSize(30);
threadPoolTaskExecutor.setQueueCapacity(100);
threadPoolTaskExecutor.afterPropertiesSet();
return threadPoolTaskExecutor;
}

 }

异步类:

@Component
public class MyAsyncTask {
@Async("MyExecutor")
public void asyncCpsItemImportTask(Long platformId, String jsonList){}
}

    注:

         1、 @Async注解由于是异步执行的,在其调用数据库操作之时,将无法产生事务管理的控制。解决办法,可以把@Transactional注解放到内部的需要进行事务的方法上

         2、异步的业务逻辑处理场景 有两种,一个是不需要返回结果,另一种是需要接收返回结果。

              不需要返回结果的比较简单,就不多说了。

              需要接收返回结果的示例如下:

   @Async("MyExecutor")
    public Future<Map<Long, List>> queryMap(List ids) {
        List<> result = businessService.queryMap(ids);
         ..............
        Map<Long, List> resultMap = Maps.newHashMap();
         ...
        return new AsyncResult<>(resultMap);
    }
调用的方法示例:
    private Map asyncCollectProcessAbilities(List<BindDeviceDO> bindDevices,
                                                            List<BindStaffDO> bindStaffs, String dccId) {
        // 返回值
        Future<Map<Long, List>> asyncResult = MyService.queryMap(ids);
        try {
            finalMap = asyncResult.get();
           
        } catch (InterruptedException | ExecutionException e) {
            ...
        }
        return finalMap;
    }

        3、关于执行器

        Spring用TaskExecutor和TaskScheduler接口提供了异步执行和调度任务的抽象。
        Spring的TaskExecutor和java.util.concurrent.Executor接口时一样的,这个接口只有一个方法execute(Runnable task)。

        Spring已经内置了许多TaskExecutor的实现,没有必要自己去实现:
             SimpleAsyncTaskExecutor  这种实现不会重用任何线程,每次调用都会创建一个新的线程。
            SyncTaskExecutor  这种实现不会异步的执行
            ConcurrentTaskExecutor  这种实现是java.util.concurrent.Executor的一个adapter。
             SimpleThreadPoolTaskExecutor  这种实现实际上是Quartz的SimpleThreadPool的一个子类,它监听Spring的声明周期回调。
            ThreadPoolTaskExecutor  这是最常用最通用的一种实现。它包含了java.util.concurrent.ThreadPoolExecutor的属性,并且用TaskExecutor进行包装。

                默认是用代理去处理@Async的,因此,相同类中的方法调用带@Async的方法是无法异步的,这种情况仍然是同步。

 

posted @ 2019-08-08 17:19  xuzhujack  阅读(9626)  评论(2编辑  收藏  举报
;