java springBoot总结-异步调用

时间:2025-08-26 20:24:01来源:互联网

下面小编就为大家分享一篇java springBoot总结-异步调用,具有很好的参考价值,希望对大家有所帮助。

@Async做异步

注解说明:

  • 在方法上使用该@Async注解,申明该方法是一个异步任务
  • 在类上面使用该@Async注解,申明该类中的所有方法都是异步任务
  • 使用此注解的方法的类对象,必须是spring管理下的bean对象
  • 需要在主类)(启动类)上开启异步配置,即,配置上@EnableAsync注解;
  • 如果不指定线程池的名称,则使用Spring默认的线程池,Spring默认的线程池为SimpleAsyncTaskExecutor
  • 方法上一旦标记了这个@Async注解,当其它线程调用这个方法时,就会开启一个新的子线程去异步处理该业务逻辑
  • 可以把@Transactional注解放到内部的需要进行事务的方法上。避免放在外部导致事务管不到异步线程

SimpleAsyncTaskExecutor默认线程池说明

默认线程池采用spring-boot-autoconfigure中task包的TaskExecutionProperties中的配置

2.3.2.RELEASE中的配置为

默认核心线程数:8
最大线程数:Integet.MAX_VALUE
队列使用LinkedBlockingQueue
容量是:Integet.MAX_VALUE
空闲线程保留时间:60s
线程池拒绝策略:AbortPolicy

存在的问题:并发情况下,会无限创建线程

可以修改默认线程池的配置

spring:
  task:
    execution:
      pool:
        max-size: 6
        core-size: 3
        keep-alive: 3s
        queue-capacity: 1000
        thread-name-prefix: xgss-thread

也可以采用自定义线程池,可以查看示例

 @Async的原理

@Async 的原理是通过 Spring AOP 动态代理 的方式来实现的。
        Spring容器启动初始化bean时,判断类中是否使用了@Async注解,如果使用了则为其创建切入点和切入点处理器,根据切入点创建代理,在线程调用@Async注解标注的方法时,会调用代理,执行切入点处理器invoke方法,将方法的执行提交给线程池中的另外一个线程来处理,从而实现了异步执行。
        所以,需要注意的一个错误用法是,如果a方法调用它同类中的标注@Async的b方法,是不会异步执行的,因为从a方法进入调用的都是该类对象本身,不会进入代理类。
        因此,相同类中的方法调用带@Async的方法是无法异步的,这种情况仍然是同步。

示例

自定义线程池

可以在@Been注解中指定线程池的名称,如果线程池名称跟默认线程池名称一样都是taskExcutor就会使用我们自己的配置

@Configuration
@Data
public class ExecutorConfig{
    /**
     * 核心线程
     */
    private int corePoolSize;
    /**
     * 最大线程
     */
    private int maxPoolSize;
    /**
     * 队列容量
     */
    private int queueCapacity;
    /**
     * 保持时间
     */
    private int keepAliveSeconds;
    /**
     * 名称前缀
     */
    private String preFix;
 
    @Bean("xgssExecutor")
    public Executor myExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(corePoolSize);
        executor.setMaxPoolSize(maxPoolSize);
        executor.setQueueCapacity(queueCapacity);
        executor.setKeepAliveSeconds(keepAliveSeconds);
        executor.setThreadNamePrefix(preFix);
        executor.setRejectedExecutionHandler( new ThreadPoolExecutor.AbortPolicy());
        executor.initialize();
        return executor;
    }
}

 

启动类开启异步

@EnableAsync
@SpringBootApplication
public class ManageApplication {
    //...
}

方法上使用注解来使其异步执行

@Component
public class MyAsyncTask {
     @Async("xgssExecutor") //使用自定义的线程池(执行器),如果不指定执行器名称走spring默认线程池
    public void asyncCpsItemImportTask(Long platformId, String jsonList){
        //...具体业务逻辑
    }
}

 

如果使用默认的线程池名字,@Async注解上不需指定线程池名称:

异步任务需要返回值的情况

@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);
}

调用异步方法的示例:

public Map<Long, List> asyncProcess(List<BindDeviceDO> bindDevices,List<BindStaffDO> bindStaffs, String dccId) {
        Map<Long, List> finalMap =null;
        // 返回值:
        Future<Map<Long, List>> asyncResult = MyService.queryMap(ids);
        try {
            finalMap = asyncResult.get();
        } catch (Exception e) {
            ...
        }
        return finalMap;
}

 

本站部分内容转载自互联网,如果有网站内容侵犯了您的权益,可直接联系我们删除,感谢支持!