SpringBoot如何实现并发任务并返回结果

 更新时间:2023年07月21日 14:23:05   作者:倔强100%  
这篇文章主要介绍了SpringBoot如何实现并发任务并返回结果问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

SpringBoot并发任务并返回结果

并发的实现以及结果获取

并发即多个线程同时进行任务,即异步任务,以下例子测试了并发进行四个任务,并同时返回结果的案例。

service层

@Service
public class AsyncTest {
        @Async
        public Future<Boolean> doReturn1(){
            try {
                // 这个方法需要调用500毫秒
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            for (int i = 0; i < 10; i++) {
                System.out.println("一号线程:"+i);
            }
            // 消息汇总
            return new AsyncResult<>(true);
        }
        @Async
        public Future<Boolean> doReturn2(){
            try {
                // 这个方法需要调用500毫秒
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            for (int i = 0; i < 10; i++) {
                System.out.println("二号线程:"+i);
            }
            // 消息汇总
            return new AsyncResult<>(true);
        }
        @Async
        public Future<Boolean> doReturn3(){
            try {
                // 这个方法需要调用500毫秒
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            for (int i = 0; i < 10; i++) {
                System.out.println("三号线程:"+i);
            }
            // 消息汇总
            return new AsyncResult<>(true);
        }
        @Async
        public Future<Boolean> doReturn4(){
            try {
                // 这个方法需要调用500毫秒
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            for (int i = 0; i < 10; i++) {
                System.out.println("四号线程:"+i);
            }
            // 消息汇总
            return new AsyncResult<>(true);
        }
}

controller层

@RequestMapping("/async")
    public String async(){
        List<Future<Boolean>> futures = new ArrayList<>();
        Future<Boolean> flag1 = asyncTest.doReturn1();
        Future<Boolean> flag2 = asyncTest.doReturn2();
        Future<Boolean> flag3 = asyncTest.doReturn3();
        Future<Boolean> flag4 = asyncTest.doReturn4();
        futures.add(flag1);
        futures.add(flag2);
        futures.add(flag3);
        futures.add(flag4);
        List<Boolean> response = new ArrayList<>();
        for (Future future : futures) {
            Boolean flag = null;
            try {
                flag = (Boolean) future.get();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
            response.add(flag);
        }
        System.out.println(response);
        return response.toString();
    }

这种方法即可在并发的时候拦截到全部完成后的结果进行判断,满足才进行下一步。

SpringBoot并发配置

Spring Boot 提供了一些默认的并发配置,可以通过配置文件或代码进行调整。

下面介绍一些常用的 Spring Boot 并发配置:

线程池配置

可以在 application.properties 或 application.yml 文件中配置线程池的参数,例如最大线程数、核心线程数等:

# application.yml
spring:
  task:
    execution:
      pool:
        max-threads: 10
        core-threads: 5

异步处理配置

可以通过 @EnableAsync 注解开启异步处理,并且可以配置线程池的参数:

@Configuration
@EnableAsync
public class AppConfig {
    @Bean
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(25);
        return executor;
    }
}

WebMvc 配置

可以通过配置 WebMvcConfigurerAdapter 来配置 Spring Boot 的 MVC 框架的线程池大小和异步处理:

@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
    @Override
    public void configureAsyncSupport(final AsyncSupportConfigurer configurer) {
        configurer.setTaskExecutor(asyncTaskExecutor());
    }
    @Bean
    public AsyncTaskExecutor asyncTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(50);
        executor.setQueueCapacity(100);
        executor.setThreadNamePrefix("MySpringAsyncThread-");
        executor.initialize();
        return executor;
    }
}

Tomcat 连接器配置

Tomcat 是 Spring Boot 的默认 Web 服务器,可以通过配置 Tomcat 的连接器参数来进行并发调优:

server:
    tomcat:
        max-connections:2000
        max-threads:200
        min-spare-threads:10
        accept-count:100

undertow 配置

如果springboot 配置undertow作为web服务器 则可通过如下参数进行并发调优

  # undertow 配置
  undertow:
    # HTTP post内容的最大大小。当值为-1时,默认值为大小是无限的
    max-http-post-size: -1
    # 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理
    # 每块buffer的空间大小,越小的空间被利用越充分
    buffer-size: 512
    # 是否分配的直接内存
    direct-buffers: true
    threads:
      # 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程
      io: 8
      # 阻塞任务线程池, 当执行类似servlet请求阻塞操作, undertow会从这个线程池中取得线程,它的值设置取决于系统的负载
      worker: 256

其中 max-connections 表示最大连接数,max-threads 表示最大线程数,min-spare-threads 表示最小空闲线程数,accept-count 表示请求等待队列的大小。

综上所述,可以通过线程池配置、异步处理配置、WebMvc 配置以及 Tomcat 连接器配置来调整 Spring Boot 应用的并发性能和并发能力。在实际应用中,需要结合具体的业务场景和系统架构来进行配置和优化。

通常需要考虑硬件性能、IO模型、网络、压测、服务器监控的实际数据。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 解决Spring Security升级到5.5.7、5.6.4及以上启动报错出现版本不兼容的问题

    解决Spring Security升级到5.5.7、5.6.4及以上启动报错出现版本不兼容的问题

    这篇文章主要介绍了解决Spring Security升级到5.5.7、5.6.4及以上启动报错出现版本不兼容的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • springboot vue 跨域问题的解决

    springboot vue 跨域问题的解决

    这篇文章主要介绍了springboot vue 跨域问题的解决,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-10-10
  • 如何解决项目中java heap space的问题

    如何解决项目中java heap space的问题

    这篇文章主要介绍了如何解决项目中java heap space的问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-07-07
  • 使用 Spring AI + Ollama 构建生成式 AI 应用的方法

    使用 Spring AI + Ollama 构建生成式 AI 应用的方法

    通过集成SpringBoot和Ollama,本文详细介绍了如何构建生成式AI应用,首先,介绍了AI大模型服务的两种实现方式,选择使用ollama进行部署,随后,通过SpringBoot+SpringAI来实现应用构建,本文为开发者提供了一个实用的指南,帮助他们快速入门生成式AI应用的开发
    2024-11-11
  • Mybatis的Mapper代理对象生成及调用过程示例详解

    Mybatis的Mapper代理对象生成及调用过程示例详解

    这篇文章主要为大家介绍了Mybatis的Mapper代理对象生成及调用过程示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • 保证缓存和数据库的数据一致性详解

    保证缓存和数据库的数据一致性详解

    在实际开发过程中,缓存的使用频率是非常高的,只要使用缓存和数据库存储,就难免会出现双写时数据一致性的问题,本文主要介绍了如何保证缓存和数据库的数据一致性,需要的小伙伴可以参考阅读
    2023-04-04
  • MAC下如何设置JDK环境变量

    MAC下如何设置JDK环境变量

    这篇文章主要介绍了MAC下如何设置JDK环境变量问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • 使用Java设置字型和颜色的方法详解

    使用Java设置字型和颜色的方法详解

    这篇文章主要介绍了使用Java设置字型和颜色的方法,在Java的绘图等图形化编程中较常用到,需要的朋友可以参考下
    2015-10-10
  • java 生成xml并转为字符串的方法

    java 生成xml并转为字符串的方法

    今天小编就为大家分享一篇java 生成xml并转为字符串的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-07-07
  • 详解java中接口与抽象类的区别

    详解java中接口与抽象类的区别

    这篇文章主要介绍了详解java中接口与抽象类的区别的相关资料,希望通过本文能帮助到大家,让大家轻松理解掌握接口与抽象类的区别,需要的朋友可以参考下
    2017-10-10

最新评论