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

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
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
相关文章
|
15天前
|
存储 安全 Java
Java多线程编程的艺术:从基础到实践####
本文深入探讨了Java多线程编程的核心概念、应用场景及其实现方式,旨在帮助开发者理解并掌握多线程编程的基本技能。文章首先概述了多线程的重要性和常见挑战,随后详细介绍了Java中创建和管理线程的两种主要方式:继承Thread类与实现Runnable接口。通过实例代码,本文展示了如何正确启动、运行及同步线程,以及如何处理线程间的通信与协作问题。最后,文章总结了多线程编程的最佳实践,为读者在实际项目中应用多线程技术提供了宝贵的参考。 ####
|
12天前
|
监控 安全 Java
Java中的多线程编程:从入门到实践####
本文将深入浅出地探讨Java多线程编程的核心概念、应用场景及实践技巧。不同于传统的摘要形式,本文将以一个简短的代码示例作为开篇,直接展示多线程的魅力,随后再详细解析其背后的原理与实现方式,旨在帮助读者快速理解并掌握Java多线程编程的基本技能。 ```java // 简单的多线程示例:创建两个线程,分别打印不同的消息 public class SimpleMultithreading { public static void main(String[] args) { Thread thread1 = new Thread(() -> System.out.prin
|
15天前
|
Java UED
Java中的多线程编程基础与实践
【10月更文挑战第35天】在Java的世界中,多线程是提升应用性能和响应性的利器。本文将深入浅出地介绍如何在Java中创建和管理线程,以及如何利用同步机制确保数据一致性。我们将从简单的“Hello, World!”线程示例出发,逐步探索线程池的高效使用,并讨论常见的多线程问题。无论你是Java新手还是希望深化理解,这篇文章都将为你打开多线程的大门。
|
25天前
|
缓存 Java 调度
Java中的多线程编程:从基础到实践
【10月更文挑战第24天】 本文旨在为读者提供一个关于Java多线程编程的全面指南。我们将从多线程的基本概念开始,逐步深入到Java中实现多线程的方法,包括继承Thread类、实现Runnable接口以及使用Executor框架。此外,我们还将探讨多线程编程中的常见问题和最佳实践,帮助读者在实际项目中更好地应用多线程技术。
24 3
|
27天前
|
监控 安全 Java
Java多线程编程的艺术与实践
【10月更文挑战第22天】 在现代软件开发中,多线程编程是一项不可或缺的技能。本文将深入探讨Java多线程编程的核心概念、常见问题以及最佳实践,帮助开发者掌握这一强大的工具。我们将从基础概念入手,逐步深入到高级主题,包括线程的创建与管理、同步机制、线程池的使用等。通过实际案例分析,本文旨在提供一种系统化的学习方法,使读者能够在实际项目中灵活运用多线程技术。
|
25天前
|
缓存 安全 Java
Java中的多线程编程:从基础到实践
【10月更文挑战第24天】 本文将深入探讨Java中的多线程编程,包括其基本原理、实现方式以及常见问题。我们将从简单的线程创建开始,逐步深入了解线程的生命周期、同步机制、并发工具类等高级主题。通过实际案例和代码示例,帮助读者掌握多线程编程的核心概念和技术,提高程序的性能和可靠性。
13 2
|
26天前
|
Java
Java中的多线程编程:从基础到实践
本文深入探讨Java多线程编程,首先介绍多线程的基本概念和重要性,接着详细讲解如何在Java中创建和管理线程,最后通过实例演示多线程的实际应用。文章旨在帮助读者理解多线程的核心原理,掌握基本的多线程操作,并能够在实际项目中灵活运用多线程技术。
|
28天前
|
数据采集 Java 数据安全/隐私保护
Spring Boot 3.3中的优雅实践:全局数据绑定与预处理
【10月更文挑战第22天】 在Spring Boot应用中,`@ControllerAdvice`是一个强大的工具,它允许我们在单个位置处理多个控制器的跨切面关注点,如全局数据绑定和预处理。这种方式可以大大减少重复代码,提高开发效率。本文将探讨如何在Spring Boot 3.3中使用`@ControllerAdvice`来实现全局数据绑定与预处理。
61 2
|
1月前
|
Java API 调度
Java中的多线程编程:理解与实践
本文旨在为读者提供对Java多线程编程的深入理解,包括其基本概念、实现方式以及常见问题的解决方案。通过阅读本文,读者将能够掌握Java多线程编程的核心知识,提高自己在并发编程方面的技能。
|
30天前
|
安全 Java
Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧
【10月更文挑战第20天】Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧,包括避免在循环外调用wait()、优先使用notifyAll()、确保线程安全及处理InterruptedException等,帮助读者更好地掌握这些方法的应用。
19 1
下一篇
无影云桌面