SpringBoot-27- @Async实现异步调用 什么是异步调用

简介: 异步调用是相对于同步调用的,同步调用是按照顺序进行执行任务,只有上一个任务执行完成下一个任务才能执行,异步调用是指在按照顺序执行任务的过程中不需要等待任务结果的出现,就可以顺序执行下一个任务。

SpringBoot-27- @Async实现异步调用

什么是异步调用


异步调用是相对于同步调用的,同步调用是按照顺序进行执行任务,只有上一个任务执行完成下一个任务才能执行,异步调用是指在按照顺序执行任务的过程中不需要等待任务结果的出现,就可以顺序执行下一个任务


异步处理的方式:

  • Java异步处理:Thread/Runnable、Callable/Future
  • Servlet 3.0异步处理: asyncSupported、AsyncContext
  • Spring MVC异步处理: @Async、AsyncTaskExecutor


SpringBoot自身没有对异步调用做很大的变动,基本还是使用SpringMVC的@Async

开启异步调用配置

@EnableAsync
@Configuration
public class MyEnableAsyncConfig {
}


注解:在使用**@EnableWebMvc**注解的时候也可以开启异步调用,但是在SpringBoot中使用异步调用会使得SpringBoot的AutoConfig一部分功能失效。


定义线程池

定义一个或者多个线程池

@EnableAsync
@Configuration
public class MyEnableAsyncConfig {
    @Bean(name = "threadPoolTaskExecutor1")
    public Executor taskExecutor1() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(20);
        executor.setQueueCapacity(200);
        executor.setKeepAliveSeconds(60);
        executor.setThreadNamePrefix("threadPoolTaskExecutor1-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return executor;
    }
    @Bean(name = "threadPoolTaskExecutor2")
    public Executor threadPoolTaskExecutor2() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(20);
        executor.setQueueCapacity(200);
        executor.setKeepAliveSeconds(60);
        executor.setThreadNamePrefix("threadPoolTaskExecutor2-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return executor;
    }
}



我们使用ThreadPoolTaskExecutor创建线程池,其参数配置如下:


CorePoolSize:设置核心线程数,线程池创建的时候创建线程的个数


MaxPoolSize:最大线程数,在换成队列满以后才会申请超过核心线程的线程


QueueCapacity:缓冲队列,用来缓冲执行任务的队列


KeepAliveSeconds:当超过了核心线程数之外的线程在空闲时间到达之后会被销毁


ThreadNamePrefix:线程名称前缀

定义异步调用方法

异步调用方法有两种一个是没有返回值的,一种是有返回值的,具体实现如下:

@Component
public class ComponentTask {
    public static Random random =new Random();
    /**
     * 无返回值
     */
    @Async("threadPoolTaskExecutor2")
    public void asyncMethodWithVoidReturnType_One() throws InterruptedException {
        System.out.println("开始做asyncMethodWithVoidReturnType_One");
        long start = System.currentTimeMillis();
        Thread.sleep(random.nextInt(1000));
        long end = System.currentTimeMillis();
        System.out.println("完成asyncMethodWithVoidReturnType_One,耗时:" + (end - start) + "毫秒"+"  threadname:"+Thread.currentThread().getName());
    }
    @Async("threadPoolTaskExecutor1")
    public void asyncMethodWithVoidReturnType_Two() throws InterruptedException {
        System.out.println("开始做asyncMethodWithVoidReturnType_Two");
        long start = System.currentTimeMillis();
        Thread.sleep(random.nextInt(2000));
        long end = System.currentTimeMillis();
        System.out.println("完成asyncMethodWithVoidReturnType_Two,耗时:" + (end - start) + "毫秒" +"  threadname:"+Thread.currentThread().getName());
    }
    @Async("threadPoolTaskExecutor1")
    public void asyncMethodWithVoidReturnType_Three() throws InterruptedException {
        System.out.println("开始做asyncMethodWithVoidReturnType_Three");
        long start = System.currentTimeMillis();
        Thread.sleep(random.nextInt(3000));
        long end = System.currentTimeMillis();
        System.out.println("完成asyncMethodWithVoidReturnType_Three,耗时:" + (end - start) + "毫秒"+ "  threadname:"+Thread.currentThread().getName());
    }
    /**
     * 有返回值的
     * @return
     */
    @Async("threadPoolTaskExecutor1")
    public Future<String> asyncMethodWithReturnType_One() throws InterruptedException {
        System.out.println("开始asyncMethodWithReturnType_One");
        long start = System.currentTimeMillis();
        Thread.sleep(random.nextInt(10000));
        long end = System.currentTimeMillis();
        System.out.println("完成asyncMethodWithReturnType_One,耗时:" + (end - start) + "毫秒");
        return new AsyncResult<>("任务一完成");
    }
}


在多线程池的时候,我们需要在@Async()指定线程池名称**@Async(“threadPoolTaskExecutor1”)**

单元测试

@SpringBootTest
class SpringBootPart27ApplicationTests {
    @Autowired
    private ComponentTask componentTask;
    @Test
    void contextLoads() throws InterruptedException {
        componentTask.asyncMethodWithVoidReturnType_One();
        componentTask.asyncMethodWithVoidReturnType_Two();
        componentTask.asyncMethodWithVoidReturnType_Three();
        Thread.currentThread().join();
    }
}


在单元测试用例中,注入Task对象,并在测试用例中执行asyncMethodWithVoidReturnType_One、asyncMethodWithVoidReturnType_Two()、asyncMethodWithVoidReturnType_Three()三个函数。


执行结果如下:

开始做asyncMethodWithVoidReturnType_One
开始做asyncMethodWithVoidReturnType_Two
开始做asyncMethodWithVoidReturnType_Three
完成asyncMethodWithVoidReturnType_One,耗时:435毫秒  threadname:threadPoolTaskExecutor2-1
完成asyncMethodWithVoidReturnType_Two,耗时:1885毫秒  threadname:threadPoolTaskExecutor1-1
完成asyncMethodWithVoidReturnType_Three,耗时:1904毫秒  threadname:threadPoolTaskExecutor1-2


如果您觉得本文不错,欢迎关注,点赞,收藏支持,您的关注是我坚持的动力!

目录
相关文章
|
2月前
|
并行计算 Java 数据处理
SpringBoot高级并发实践:自定义线程池与@Async异步调用深度解析
SpringBoot高级并发实践:自定义线程池与@Async异步调用深度解析
190 0
|
Java API Spring
【Springboot】springboot 多线程@EnableAsync和@Async
【Springboot】springboot 多线程@EnableAsync和@Async
97 0
|
7月前
|
Java 测试技术 Spring
Spring Boot使用@Async实现异步调用
Spring Boot使用@Async实现异步调用
53 0
|
4月前
|
Java 开发者 Spring
【SpringBoot 异步魔法】@Async 注解:揭秘 SpringBoot 中异步方法的终极奥秘!
【8月更文挑战第25天】异步编程对于提升软件应用的性能至关重要,尤其是在高并发环境下。Spring Boot 通过 `@Async` 注解简化了异步方法的实现。本文详细介绍了 `@Async` 的基本用法及配置步骤,并提供了示例代码展示如何在 Spring Boot 项目中创建与管理异步任务,包括自定义线程池、使用 `CompletableFuture` 处理结果及异常情况,帮助开发者更好地理解和运用这一关键特性。
224 1
|
4月前
|
Java Scala Kotlin
SpringBoot中@Async的实现方式探索
本文探讨了一段重写了默认`@Async`线程处理的Scala代码,并对其目的与必要性提出了疑问。原代码通过自定义`AsyncExecutorConfig`类,实现了`AsyncConfigurerSupport`接口,进而配置了一个`ThreadPoolExecutor`作为异步任务的执行器。文章随后分析了为何要替换默认实现,并对Spring框架中`@Async`注解的默认行为进行了深入研究。
|
7月前
|
Java Spring
SpringBoot+async异步调用接口以及几个任务同时完成和异步接口实现和调用
SpringBoot+async异步调用接口以及几个任务同时完成和异步接口实现和调用
139 0
|
7月前
|
监控 Java
【十一】springboot整合异步调用并获取返回值
【十一】springboot整合异步调用并获取返回值
151 0
|
7月前
|
Java Spring
SpringBoot @Async 注解
【1月更文挑战第1天】SpringBoot @Async 注解
|
7月前
|
Java Spring
SpringBoot - @Async异步任务与线程池
SpringBoot - @Async异步任务与线程池
235 1
|
7月前
|
Java Spring
使用spring boot的@Async实现异步调用和线程池复用
使用spring boot的@Async实现异步调用和线程池复用
102 0