Spring Boot通过@Async注解实现异步调用

@Aysnc其实是Spring内的一个组件,可以完成对类内单个或者多个方法实现异步调用,这样可以大大的节省等待耗时。内部实现机制是线程池任务ThreadPoolTaskExecutor,通过线程池来对配置@Async的方法或者类做出执行动作。

线程任务池配置

我们创建一个ListenerAsyncConfiguration,并且使用@EnableAsync注解开启支持异步处理,具体代码如下所示:

@Configuration
@EnableAsync
public class ListenerAsyncConfiguration implements AsyncConfigurer {
    /**
     * 获取异步线程池执行对象
     * @return
     */
    @Override
    public Executor getAsyncExecutor() {
        //使用Spring内置线程池任务对象
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        //设置线程池参数
        taskExecutor.setCorePoolSize(5);
        taskExecutor.setMaxPoolSize(10);
        taskExecutor.setQueueCapacity(25);
        taskExecutor.initialize();
        return taskExecutor;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return null;
    }
}

异步调用测试

任务类

@Slf4j
@Component
public class AsyncTask {
    @Async
    public void doTask1() {
        try {
            long start = System.currentTimeMillis();
            Thread.sleep(3000);
            long end = System.currentTimeMillis();
            log.info("任务1结束, 耗时: " + (end-start));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Async
    public void doTask2() {
        try {
            long start = System.currentTimeMillis();
            Thread.sleep(3000);
            long end = System.currentTimeMillis();
            log.info("任务2结束, 耗时: " + (end-start));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Async
    public void doTask3() {
        try {
            long start = System.currentTimeMillis();
            Thread.sleep(5000);
            long end = System.currentTimeMillis();
            log.info("任务3结束, 耗时: " + (end-start));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

控制器

@Slf4j
@RestController
public class AsyncController {
    @Autowired
    private AsyncTask asyncTask;

    @RequestMapping("/async")
    public String async() {
        long start = System.currentTimeMillis();
        asyncTask.doTask1();
        asyncTask.doTask2();
        asyncTask.doTask3();
        long end = System.currentTimeMillis();
        log.info("请求耗时: " + (end-start));
        return "SUCCESS";
    }
}

输出结果

请求耗时: 4
任务2结束, 耗时: 3001
任务1结束, 耗时: 3001
任务3结束, 耗时: 5001

带有返回值的方法如何使用@Async注解

使用@Async注解的方法返回值为java.util.concurrent.Future的实现类org.springframework.scheduling.annotation.AsyncResult类型

任务类

@Slf4j
@Component
public class AsyncTaskWithResult {
    @Async
    public Future<String> doTask1() {
        try {
            long start = System.currentTimeMillis();
            Thread.sleep(3000);//静静的沉睡3秒钟
            long end = System.currentTimeMillis();
            log.info("任务1结束, 耗时: " + (end-start));
            return new AsyncResult<String>("Aysnc task 1 is done");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Async
    public Future<String> doTask2() {
        try {
            long start = System.currentTimeMillis();
            Thread.sleep(3000);//静静的沉睡3秒钟
            long end = System.currentTimeMillis();
            log.info("任务2结束, 耗时: " + (end-start));
            return new AsyncResult<String>("Aysnc task 2 is done");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Async
    public Future<String> doTask3() {
        try {
            long start = System.currentTimeMillis();
            Thread.sleep(5000);//静静的沉睡5秒钟
            long end = System.currentTimeMillis();
            log.info("任务3结束, 耗时: " + (end-start));
            return new AsyncResult<String>("Aysnc task 3 is done");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

控制器

@Slf4j
@RestController
public class AsyncController {
    @Autowired
    private AsyncTaskWithResult asyncTaskWithResult;

    @RequestMapping("/async_return")
    public String asyncReturn() {
        long start = System.currentTimeMillis();
        Future<String> async1 = asyncTaskWithResult.doTask1();
        Future<String> async2 = asyncTaskWithResult.doTask2();
        Future<String> async3 = asyncTaskWithResult.doTask3();
        try {
            while (true) {
                if (async1 != null && async1.isDone()) {
                    log.info("任务1返回: " + async1.get());
                }
                if (async2 != null && async2.isDone()) {
                    log.info("任务2返回: " + async2.get());
                }
                if (async3 != null && async3.isDone()) {
                    log.info("任务3返回: " + async3.get());
                }
                if ((async1 == null || async1.isDone()) &&
                    (async2 == null || async2.isDone()) &&
                    (async3 == null || async3.isDone())) {
                    break;
                }
                Thread.sleep(1000);
            }
        } catch (Exception e) {

        }
        long end = System.currentTimeMillis();
        log.info("请求耗时: " + (end-start));
        return "SUCCESS";
    }
}

输出结果

任务2结束, 耗时: 3000
任务1结束, 耗时: 3000
任务1返回: Aysnc task 1 is done
任务2返回: Aysnc task 2 is done
任务3结束, 耗时: 5001
任务1返回: Aysnc task 1 is done
任务2返回: Aysnc task 2 is done
任务3返回: Aysnc task 3 is done
请求耗时: 5017

版权声明:
作者:Joe.Ye
链接:https://www.appblog.cn/index.php/2023/03/09/spring-boot-implement-asynchronous-call-through-async-annotation/
来源:APP全栈技术分享
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
打赏
海报
Spring Boot通过@Async注解实现异步调用
@Aysnc其实是Spring内的一个组件,可以完成对类内单个或者多个方法实现异步调用,这样可以大大的节省等待耗时。内部实现机制是线程池任务ThreadPoolTaskExecut……
<<上一篇
下一篇>>
文章目录
关闭
目 录