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

举报
小马哥学JAVA 发表于 2023/02/18 17:50:08 2023/02/18
【摘要】 前言:关于多线程的异步处理,由于项目的需求有个方法需要使用异步的方法来调用,方法是调用外部的接口,执行时间会比较长导致的没有办法同步拿去到结果,所以需要写一个异步线程的方法进行该接口的调用,下面是一个案例以及自己测试的异步结果的情况;第一步:需要是项目启动的初始化启动异步的配置处理第二步:需要创建config进行配置相关线程池的处理@Configurationpublic class Spr...
前言:

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

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

image

第二步:需要创建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 captureMapData = DataCaptureContext.getMapData();

                Map 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 captureMapData = DataCaptureContext.getMapData();

                Map 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 captureMapData = DataCaptureContext.getMapData();

                Map 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;

    }

}

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

image

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

image

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

image

总结:

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

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

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

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。