本文介绍: 方法异步执行是通过线程池来执行的, spring默认会从beanFactory尝试获取TaskExecutor类型bean,如果获取不到,就会继续尝试获取bean name为’taskExecutor’的bean,还获取不到就创建一个SimpleAsyncTaskExecutor类型的执行器。异步执行的原理还是通过@EnableAsync引入对应的bean后置处理器,来使用advisor对@Async标识的方法进行代理增强。添加@Async注解的方法必须是public的。因为使用动态代理

在一些后台耗时的场景比如说生成统计报表,生成数据文件,执行批量任务时候,需要异步执行,先登记信息然后异步执行批量同步返回客户端。在spring中要想使用异步方法执行,必须使用@EnableAsync注解开启async

开启异步执行配置

@Configuration
@EnableAsync
@ComponentScan(basePackages = {"com.cpx.service.async"})
public class AsyncConfig {
  
}

然后需要异步执行的方法上添加@Async注解

@Service
public class AsyncService {

    @Async
    public void exec(){
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(LocalDateTime.now().toString() +":exec end");
    }
}

添加@Async注解的方法必须是public的。方法所属的类必须是一个bean才能被扫描到。this方式调用异步方法是没有效果的。因为使用的动态代理

测试方法的异步执行:

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AsyncConfig.class);
AsyncService asyncService = (AsyncService) ctx.getBean("asyncService");
System.out.println(LocalDateTime.now().toString()+" start");
asyncService.exec();//该方法调用会异步执行
System.out.println(LocalDateTime.now().toString()+" main end");
ctx.close();

TaskExecutor

方法的异步执行是通过线程池来执行的, spring默认会从beanFactory尝试去获取TaskExecutor类型bean,如果获取不到,就会继续尝试获取bean name为’taskExecutor’的bean,还获取不到就创建一个SimpleAsyncTaskExecutor类型的执行器。SimpleAsyncTaskExecutor每来一个任务启动一个Thread来执行任务,不会重复利用。这么看SimpleAsyncTaskExecutor不是一个严格意义的线程池,线程并不会重用。如果高并发耗时任务可能会导致一定的内存使用问题这里可以指定线程池。

第一种通过实现AsyncConfigurer接口然后重写getAsyncExecutor()方法。

public class AsyncConfig implements AsyncConfigurer {

    @Override
    public Executor getAsyncExecutor() {
    	//自定义线程池实现
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        threadPoolTaskExecutor.initialize();
        return threadPoolTaskExecutor;
    }
}

这种线程池是所有@Async注解都可以使用,另一种可以在@Async(“taskExecutor”)注解上指定线程池名字。

返回

可以返回一个future

@Async
public Future<String> exec(){
    try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return new AsyncResult<String>("ok");
}

异常处理

返回的@Async方法异常会被封装到future里,没有返回值的可以定义一个AsyncUncaughtExceptionHandler来处理异常

public class CustomAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
    @Override
    public void handleUncaughtException(Throwable ex, Method method, Object... params) {
        System.out.println(method.getName()+",发生异常");
        //TODO
    }
}

然后实现AsyncConfigurer的bean里重写getAsyncUncaughtExceptionHandler()返回自定义的异常handler

异步执行的原理还是通过@EnableAsync引入对应的bean后置处理器,来使用advisor对@Async标识的方法进行代理增强。方法的执行会通过AsyncExecutionInterceptor代理执行。

原文地址:https://blog.csdn.net/sinat_16493273/article/details/134604035

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。

如若转载,请注明出处:http://www.7code.cn/show_5277.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注