SpringBoot高级并发实践:自定义线程池与@Async异步调用深度解析

简介: SpringBoot高级并发实践:自定义线程池与@Async异步调用深度解析

同步编程&异步编程

Java并发编程中,同步和异步是两种常见的处理方式。

同步是指多个任务按顺序执行,一个任务的执行需要等待上一个任务的完成。而异步则是指多个任务可以并行执行,不需要等待上一个任务完成。

在多线程编程中,同步是指多个线程按顺序执行,一个线程的执行需要等待上一个线程的完成;而异步是指多个线程可以并发执行,不需要等待其他线程的完成。

在实际应用中,同步通常适用于简单的线性任务,比如IO操作、数据库读写等;而异步通常适用于复杂的并发任务,比如并行计算、大规模数据处理等。

线程池

为什么要使用线程池?

当创建使用线程,需要进行new Thread操作,在JVM的堆内存中创建新的对象地址。

当使用完毕后,需要等待JVM的GC操作,检索Root根释放堆中的垃圾信息。

频繁的创建线程和销毁垃圾,极大的消耗了系统的资源,降低了处理其他业务的性能问题。

创建一个池,保存初始化的线程,用的时候取,不用的时候放入池中等待下次使用。

减少创建的线程数。

Spring自定义线程池

/**
 * @author linghu
 * 自定义线程池配置
 * 需要使用线程池,则开启当前配置
 */
@Configuration
public class ThreadPoolConfig {
    @Bean
    public ThreadPoolExecutor myThreadPool(){
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                2,//核心线程数,一直都能工作的数量
                5,//请求处理大的时候,可以开放的最大工作数、最大线程数
                3,//开启最大工作数后,当无请求时,还让其存活的时间、线程活跃时间
                TimeUnit.SECONDS,//存活时间的单位
                new LinkedBlockingDeque<>(10),//阻塞队列,保存操作请求线程
                Executors.defaultThreadFactory(),//创建线程的工厂类
                new ThreadPoolExecutor.AbortPolicy()//设置拒绝策略
        );
        return threadPoolExecutor;
    }
}

具体案例:

@RestController
public class TestController {
    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;
    @Autowired
    private MyService myService;
    @RequestMapping("/getThreadPoolInfo")
    public void getThreadPoolInfo(){
        System.out.println("getActiveCount--"+threadPoolExecutor.getActiveCount());
        System.out.println("getCorePoolSize--"+threadPoolExecutor.getCorePoolSize());
        System.out.println("getPoolSize--"+threadPoolExecutor.getPoolSize());
    }
    @RequestMapping("/test1")
    public String test1(){
        System.out.println("进入test1 "+System.currentTimeMillis());
        /** 这种调用其实比较复杂,还有更简单的调用法则 */
        threadPoolExecutor.execute(()->{
            try {
                System.out.println("线程池处理数据  start "+System.currentTimeMillis());
                TimeUnit.SECONDS.sleep(3);
                System.out.println("线程池处理数据  end "+System.currentTimeMillis());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        System.out.println("线程池调用结束 "+System.currentTimeMillis());
        return "6666";
    }
}

测试:

上面自定义的线程池能够实现异步调用执行方法。

SpringBoot轻松调用线程池

SpringBoot自定义线程池同上面的Spring,只不过多了几个注解简化了一些操作。SpringBoot能够通过这个注解更轻松的调用线程池。

我们将类上添加注解@EnableAsync 开启异步调用,让在需要使用的地方,直接使用@Async就可以了。

@Configuration
@EnableAsync//注解开启异步调用Async
public class ThreadPoolConfig {
    @Bean
    public ThreadPoolExecutor myThreadPool(){
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                2,//核心线程数,一直都能工作的数量
                5,//请求处理大的时候,可以开放的最大工作数、最大线程数
                3,//开启最大工作数后,当无请求时,还让其存活的时间、线程活跃时间
                TimeUnit.SECONDS,//存活时间的单位
                new LinkedBlockingDeque<>(10),//阻塞队列,保存操作请求线程
                Executors.defaultThreadFactory(),//创建线程的工厂类
                new ThreadPoolExecutor.AbortPolicy()//设置拒绝策略
        );
        return threadPoolExecutor;
    }
}

然后编写一个测试类,同时也需要将具体的异步业务单独独立出来:

@RequestMapping("/test2")
    public void test2() throws InterruptedException {
        System.out.println("进入test2 "+System.currentTimeMillis());
        myService.service1();
        System.out.println("调用结束 "+System.currentTimeMillis());
    }

服务类的代码如下所示:

// 具体使用哪个线程池
@Async("myThreadPoolExecutor")
public void service1() throws InterruptedException {
    System.out.println("----- service1 start --------"+System.currentTimeMillis());
    TimeUnit.SECONDS.sleep(3);
    System.out.println("----- service1 end --------"+System.currentTimeMillis());
}

执行请求:

http://localhost:8080/test2

总结

我们其实用注解 @Async("myThreadPoolExecutor")取代了

threadPoolExecutor.execute(()->{
            try {
                System.out.println("线程池处理数据  start "+System.currentTimeMillis());
                TimeUnit.SECONDS.sleep(3);
                System.out.println("线程池处理数据  end "+System.currentTimeMillis());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

测试demo链接

https://gitee.com/xiangjiaobunana/springboot-thread-pool

目录
相关文章
|
存储 Java 文件存储
微服务——SpringBoot使用归纳——Spring Boot使用slf4j进行日志记录—— logback.xml 配置文件解析
本文解析了 `logback.xml` 配置文件的详细内容,包括日志输出格式、存储路径、控制台输出及日志级别等关键配置。通过定义 `LOG_PATTERN` 和 `FILE_PATH`,设置日志格式与存储路径;利用 `&lt;appender&gt;` 节点配置控制台和文件输出,支持日志滚动策略(如文件大小限制和保存时长);最后通过 `&lt;logger&gt;` 和 `&lt;root&gt;` 定义日志级别与输出方式。此配置适用于精细化管理日志输出,满足不同场景需求。
3374 1
|
JSON 前端开发 Java
深入理解 Spring Boot 中日期时间格式化:@DateTimeFormat 与 @JsonFormat 完整实践
在 Spring Boot 开发中,日期时间格式化是前后端交互的常见痛点。本文详细解析了 **@DateTimeFormat** 和 **@JsonFormat** 两个注解的用法,分别用于将前端传入的字符串解析为 Java 时间对象,以及将时间对象序列化为指定格式返回给前端。通过完整示例代码,展示了从数据接收、业务处理到结果返回的全流程,并总结了解决时区问题和全局配置的最佳实践,助你高效处理日期时间需求。
2287 0
|
存储 Java 数据库
Spring Boot 注册登录系统:问题总结与优化实践
在Spring Boot开发中,注册登录模块常面临数据库设计、密码加密、权限配置及用户体验等问题。本文以便利店销售系统为例,详细解析四大类问题:数据库字段约束(如默认值缺失)、密码加密(明文存储风险)、Spring Security配置(路径权限不当)以及表单交互(数据丢失与提示不足)。通过优化数据库结构、引入BCrypt加密、完善安全配置和改进用户交互,提供了一套全面的解决方案,助力开发者构建更 robust 的系统。
573 0
|
前端开发 Java Spring
SpringBoot之异步调用@Ansyc
本文介绍了在Spring Boot中实现异步任务的方法,通过在启动类或线程池配置类上添加`@EnableAsync`注解开启异步功能。详细说明了线程池属性类的定义,包括核心线程数、最大线程数、队列容量等参数配置。同时,文章指出需要在目标方法上使用`@Async`注解以实现异步执行,并列举了`@Async`注解失效的多种情况,如方法被`static`修饰、类未被Spring扫描、方法调用者与被调用方法在同一类中等。此外,还探讨了解决事务与异步之间矛盾的方案,强调了正确使用`@Transactional`注解的重要性。
987 8
|
JSON 前端开发 Java
深入理解 Spring Boot 中日期时间格式化:@DateTimeFormat 与 @JsonFormat 完整实践
在 Spring Boot 开发中,处理前后端日期交互是一个常见问题。本文通过 **@DateTimeFormat** 和 **@JsonFormat** 两个注解,详细讲解了如何解析前端传来的日期字符串以及以指定格式返回日期数据。文章从实际案例出发,结合代码演示两者的使用场景与注意事项,解决解析失败、时区偏差等问题,并提供全局配置与局部注解的实践经验。帮助开发者高效应对日期时间格式化需求,提升开发效率。
4404 2
|
Java 测试技术 Spring
SpringBoot+@Async注解一起用,速度提升
本文介绍了异步调用在高并发Web应用性能优化中的重要性,对比了同步与异步调用的区别。同步调用按顺序执行,每一步需等待上一步完成;而异步调用无需等待,可提升效率。通过Spring Boot示例,使用@Async注解实现异步任务,并借助Future对象处理异步回调,有效减少程序运行时间。
461 3
|
Java 数据库 开发者
详细介绍SpringBoot启动流程及配置类解析原理
通过对 Spring Boot 启动流程及配置类解析原理的深入分析,我们可以看到 Spring Boot 在启动时的灵活性和可扩展性。理解这些机制不仅有助于开发者更好地使用 Spring Boot 进行应用开发,还能够在面对问题时,迅速定位和解决问题。希望本文能为您在 Spring Boot 开发过程中提供有效的指导和帮助。
2662 12
|
前端开发 Java Nacos
🛡️Spring Boot 3 整合 Spring Cloud Gateway 工程实践
本文介绍了如何使用Spring Cloud Alibaba 2023.0.0.0技术栈构建微服务网关,以应对微服务架构中流量治理与安全管控的复杂性。通过一个包含鉴权服务、文件服务和主服务的项目,详细讲解了网关的整合与功能开发。首先,通过统一路由配置,将所有请求集中到网关进行管理;其次,实现了限流防刷功能,防止恶意刷接口;最后,添加了登录鉴权机制,确保用户身份验证。整个过程结合Nacos注册中心,确保服务注册与配置管理的高效性。通过这些实践,帮助开发者更好地理解和应用微服务网关。
2691 0
🛡️Spring Boot 3 整合 Spring Cloud Gateway 工程实践
|
存储 监控 小程序
Java中的线程池优化实践####
本文深入探讨了Java中线程池的工作原理,分析了常见的线程池类型及其适用场景,并通过实际案例展示了如何根据应用需求进行线程池的优化配置。文章首先介绍了线程池的基本概念和核心参数,随后详细阐述了几种常见的线程池实现(如FixedThreadPool、CachedThreadPool、ScheduledThreadPool等)的特点及使用场景。接着,通过一个电商系统订单处理的实际案例,分析了线程池参数设置不当导致的性能问题,并提出了相应的优化策略。最终,总结了线程池优化的最佳实践,旨在帮助开发者更好地利用Java线程池提升应用性能和稳定性。 ####
|
安全 Java 开发者
Java中的多线程编程:从基础到实践
本文深入探讨了Java多线程编程的核心概念和实践技巧,旨在帮助读者理解多线程的工作原理,掌握线程的创建、管理和同步机制。通过具体示例和最佳实践,本文展示了如何在Java应用中有效地利用多线程技术,提高程序性能和响应速度。
355 11

推荐镜像

更多
  • DNS