spring springboot关于异步线程实践案例

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: spring springboot关于异步线程实践案例
前言:

关于多线程的异步处理,由于项目的需求有个方法需要使用异步的方法来调用,方法是调用外部的接口,执行时间会比较长导致的没有办法同步拿去到结果,所以需要写一个异步线程的方法进行该接口的调用,下面是一个案例以及自己测试的异步结果的情况;

第一步:需要是项目启动的初始化启动异步的配置处理

第二步:需要创建config进行配置相关线程池的处理

@Configuration

public class SpringBootAsyncConfig {

   private static final Logger LOGGER = LoggerFactory.getLogger(SpringBootMvcConfig.class);

   @Value("${spring.async.thread.pool.core-pool-size}")

   private int corePoolSize = 10;

   @Value("${spring.async.thread.pool.max-pool-size}")

   private int maxPoolSize = 1000;

   @Value("${spring.async.thread.pool.queue-capacity}")

   private int queueCapacity = 1000;

   @Value("${spring.async.thread.pool.keep-alive-seconds}")

   private int keepAliveSeconds = 600;


   public SpringBootAsyncConfig() {

   }


   @Bean({"asyncThreadPool"})

   public TaskExecutor taskExecutor() {

       ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();

       executor.setCorePoolSize(this.corePoolSize);

       executor.setMaxPoolSize(this.maxPoolSize);

       executor.setQueueCapacity(this.queueCapacity);

       executor.setKeepAliveSeconds(this.keepAliveSeconds);

       executor.setThreadNamePrefix("AsyncThreadPool-");

       executor.setRejectedExecutionHandler(new AbortPolicy());

       executor.setTaskDecorator(new TaskDecorator() {

           public Runnable decorate(Runnable runnable) {

               Map<String, Object> captureMapData = DataCaptureContext.getMapData();

               Map<String, String> mdcMap = MDC.getCopyOfContextMap();

               return () -> {

                   try {

                       if (mdcMap != null) {

                           MDC.setContextMap(mdcMap);

                       }


                       if (captureMapData != null) {

                           DataCaptureContext.setMapData(captureMapData);

                       }


                       runnable.run();

                   } finally {

                       MDC.clear();

                       DataCaptureContext.removeMapData();

                   }


               };

           }

       });

       executor.initialize();

       return executor;

   }


   @Bean({"springSessionRedisTaskExecutor"})

   public ThreadPoolTaskExecutor springSessionRedisTaskExecutor() {

       ThreadPoolTaskExecutor springSessionRedisTaskExecutor = new ThreadPoolTaskExecutor();

       springSessionRedisTaskExecutor.setCorePoolSize(10);

       springSessionRedisTaskExecutor.setMaxPoolSize(10);

       springSessionRedisTaskExecutor.setKeepAliveSeconds(600);

       springSessionRedisTaskExecutor.setQueueCapacity(1000);

       springSessionRedisTaskExecutor.setThreadNamePrefix("Spring session redis executor thread: ");

       springSessionRedisTaskExecutor.setRejectedExecutionHandler(new DiscardPolicy());

       springSessionRedisTaskExecutor.initialize();

       return springSessionRedisTaskExecutor;

   }


   @Bean({"bankInstructionTaskExecutor"})

   public ThreadPoolTaskExecutor bankInstructionTaskExecutor() {

       ThreadPoolTaskExecutor bankInstructionTaskExecutor = new ThreadPoolTaskExecutor();

       bankInstructionTaskExecutor.setCorePoolSize(20);

       bankInstructionTaskExecutor.setMaxPoolSize(20);

       bankInstructionTaskExecutor.setKeepAliveSeconds(1800);

       bankInstructionTaskExecutor.setQueueCapacity(20);

       bankInstructionTaskExecutor.setThreadNamePrefix("bank instruction task  executor thread: ");

       bankInstructionTaskExecutor.setRejectedExecutionHandler(new DiscardPolicy());

       bankInstructionTaskExecutor.setTaskDecorator(new TaskDecorator() {

           public Runnable decorate(Runnable runnable) {

               Map<String, Object> captureMapData = DataCaptureContext.getMapData();

               Map<String, String> mdcMap = MDC.getCopyOfContextMap();

               return () -> {

                   try {

                       if (mdcMap != null) {

                           MDC.setContextMap(mdcMap);

                       }


                       if (captureMapData != null) {

                           DataCaptureContext.setMapData(captureMapData);

                       }


                       runnable.run();

                   } finally {

                       MDC.clear();

                       DataCaptureContext.removeMapData();

                   }


               };

           }

       });

       bankInstructionTaskExecutor.initialize();

       return bankInstructionTaskExecutor;

   }


   @Bean({"instructionStatusUpdateTaskExecutor"})

   public ThreadPoolTaskExecutor instructionStatusUpdateTaskExecutor() {

       ThreadPoolTaskExecutor bankInstructionTaskExecutor = new ThreadPoolTaskExecutor();

       bankInstructionTaskExecutor.setCorePoolSize(20);

       bankInstructionTaskExecutor.setMaxPoolSize(20);

       bankInstructionTaskExecutor.setKeepAliveSeconds(1800);

       bankInstructionTaskExecutor.setQueueCapacity(20);

       bankInstructionTaskExecutor.setThreadNamePrefix("instruction status update executor thread: ");

       bankInstructionTaskExecutor.setRejectedExecutionHandler(new DiscardPolicy());

       bankInstructionTaskExecutor.setTaskDecorator(new TaskDecorator() {

           public Runnable decorate(Runnable runnable) {

               Map<String, Object> captureMapData = DataCaptureContext.getMapData();

               Map<String, String> mdcMap = MDC.getCopyOfContextMap();

               return () -> {

                   try {

                       if (mdcMap != null) {

                           MDC.setContextMap(mdcMap);

                       }


                       if (captureMapData != null) {

                           DataCaptureContext.setMapData(captureMapData);

                       }


                       runnable.run();

                   } finally {

                       MDC.clear();

                       DataCaptureContext.removeMapData();

                   }


               };

           }

       });

       bankInstructionTaskExecutor.initialize();

       return bankInstructionTaskExecutor;

   }

}

第三步:在调用异步方法的时候需要进行注解的标注该方法是异步的方法

第四步:异步方法的调用执行情况如下

第五步:异步方法的调用情况二

总结:

需要注意的点有三个,也就是分为三种情况:

  1. 避免同步方法里面调用异步的方法,比如说在controller里面的类直接调用本controller里面的异步方法,这个时候是不会产生异步的效果的,还是会顺序的执行。
  2. 如果说在controller里面调用service里面的同步方法的话,同步方法里面有调用其他的异步方法,这个时候也会认为是同步的方法,也会顺序的执行,异步没有效果,也不会新开线程进行处理的。
  3. 只有在controller里面直接调用service里面的异步方法才会产生异步的效果。

综上所述,异步方法要正确的时候才会达到想要的结果,否则的话容易同步方法里面调用异步方法,导致异步方法没有效果,闹出笑话来。始终坚持学习,始终去实践测试代码,看一下执行的结果才能正确写出想要的代码,程序员一定要做到知其然知其所以然,共勉。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
1天前
|
Java 程序员 调度
Java中的多线程编程:从理论到实践
【5月更文挑战第14天】在现代计算机技术中,多线程编程是一个重要的概念。它允许多个线程并行执行,从而提高程序的运行效率。本文将从理论和实践两个角度深入探讨Java中的多线程编程,包括线程的基本概念、创建和控制线程的方法,以及如何处理线程同步和通信问题。
|
1天前
|
安全 Java Spring
Spring框架中的单例Bean是线程安全的吗?
Spring框架中的单例Bean是线程安全的吗?
10 1
|
1天前
|
Java
Java中的多线程编程:基础知识与实践
【5月更文挑战第13天】在计算机科学中,多线程是一种使得程序可以同时执行多个任务的技术。在Java语言中,多线程的实现主要依赖于java.lang.Thread类和java.lang.Runnable接口。本文将深入探讨Java中的多线程编程,包括其基本概念、实现方法以及一些常见的问题和解决方案。
|
1天前
|
监控 Java Spring
Spring Boot中一般如何使用线程池?
在Spring Boot应用程序中,合理地使用线程池可以有效地提高系统的性能和并发处理能力。本文将深入探讨Spring Boot中如何一般性地使用线程池,包括线程池的配置、使用方式以及一些最佳实践。
24 0
|
1天前
|
Java
线程安全问题-卖票案例实现
线程安全问题-卖票案例实现
11 0
|
1天前
|
设计模式 消息中间件 安全
【Java多线程】关于多线程的一些案例 —— 单例模式中的饿汉模式和懒汉模式以及阻塞队列
【Java多线程】关于多线程的一些案例 —— 单例模式中的饿汉模式和懒汉模式以及阻塞队列
11 0
|
1天前
|
数据采集 Web App开发 Java
Python 爬虫:Spring Boot 反爬虫的成功案例
Python 爬虫:Spring Boot 反爬虫的成功案例
|
1天前
|
Java
Java中的多线程编程:基础知识与实践
【5月更文挑战第5天】在现代软件开发中,多线程编程是一个重要的概念,尤其是在Java这样的多平台、高性能的编程语言中。通过多线程,我们可以实现并行处理,提高程序的运行效率。本文将介绍Java中多线程编程的基础知识,包括线程的概念、创建和控制方法,以及一些常见的多线程问题和解决方案。
|
1天前
|
Java 调度 开发者
Java中的多线程编程:基础与实践
【5月更文挑战第2天】本文将深入探讨Java中的多线程编程,从基础概念到实际应用,为读者提供全面的理解和实践指导。我们将首先介绍线程的基本概念和重要性,然后详细解析Java中实现多线程的两种主要方式:继承Thread类和实现Runnable接口。接着,我们将探讨线程同步的问题,包括synchronized关键字和Lock接口的使用。最后,我们将通过一个实际的生产者-消费者模型来演示多线程编程的实践应用。
|
1天前
|
安全 Java 程序员
Java中的多线程编程:从理论到实践
【5月更文挑战第2天】 在计算机科学中,多线程编程是一项重要的技术,它允许多个任务在同一时间段内并发执行。在Java中,多线程编程是通过创建并管理线程来实现的。本文将深入探讨Java中的多线程编程,包括线程的概念、如何创建和管理线程、以及多线程编程的一些常见问题和解决方案。
22 1