如何进行SpringMVC异步编程

前言

SpringMVC是我们平时用的最多的异步编程框架,但是我们在使用的时候基本上只是用到了它的同步编程。一般情况下是够用的,但是在并发量比较大的时候可能就不会够用了,因为一个请求会占用一个tomcat线程,这个时候我们可以尝试使用异步编程的方式来提高吞吐量。

环境准备

maven依赖:

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
        </dependency>

同步

我们在介绍异步编程之前先回顾一下同步的方式

项目结构:

controller

service

我这里只是做一下模拟操作,就不引用数据库的操作了。

这种同步的编程方式可能就是我们平时用的最多的一种形式,简单直观。

异步

首先我们需要在启动类上加上 @EnableAsync 注解开启异步支持,然后我们再定义一个Executor,这样的话我们在想要异步执行的方法上面加上@Async("asyncExecutor")注解。如果觉得每次都要指定使用哪个线程池麻烦的话,可以让我们的配置类继承AsyncConfigurerSupport然后覆写getAsyncExecutor()方法,这样我们就可以直接使用@Async而不用指定名称。

service改造

我们service返回一个AsyncResult或者 CompletableFuture,然后在方法上面加上@Async注解

虽然我们的service改造成了异步的但是如果我们在controller直接调用get方法获取值那么还是会阻塞住

controller改造

controller的异步有多种方式我这里介绍常用的三种

  • DeferredResult

DeferredResult 这个类代表延迟结果。DeferredResult 可以用在异步任务中,其他线程能够获取 DeferredResult 并设置 DeferredResult 的返回数据。通常可以使用线程池、队列等配合。我们这里直接使用之前定义的哪个线程池。

  • Callable

使用 Callable 进行异步处理与 DeferredResult 类似。不同的是,Callable 会交给系统指定的 TaskExecutor 执行。

  • WebAsyncTask

后两个默认是使用SimpleAsyncTaskExecutor,这个会为每次请求创建一个新的线程。

我们可以配置async 的线程池,不需要为每个任务单独指定。

通过configurer.setTaskExecutor(threadPoolTaskExecutor());来指定线程池。

这样就可以指定TaskExecutor了

posted @ 2023-04-03 23:32  loveletters  阅读(210)  评论(0编辑  收藏  举报