首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >spring springboot关于异步线程实践案例

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

原创
作者头像
小马哥学JAVA
发布2023-02-03 09:24:02
5800
发布2023-02-03 09:24:02
举报
文章被收录于专栏:JAVA开发专栏JAVA开发专栏
前言:

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

第一步:需要是项目启动的初始化启动异步的配置处理
第二步:需要创建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里面的异步方法才会产生异步的效果。

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言:
  • 第一步:需要是项目启动的初始化启动异步的配置处理
  • 第二步:需要创建config进行配置相关线程池的处理
  • 第三步:在调用异步方法的时候需要进行注解的标注该方法是异步的方法
  • 第四步:异步方法的调用执行情况如下
  • 总结:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档