SpringBoot环境下的多线程开发案例

讲实话以前没有写过多线程编程,这次也是参考了网上其他的案例总结了一下,并且投身到京东那边的实际项目里尝试了一下,下面说一下实际案例。

SpringBoot内其实多线程一般还是走线程池,因为线程池好控制,内部也有一定控制,拒绝策略等等,还可以最大程度发挥线程的特性,发挥cpu的性能。

先说一下,我们在线程池Executor这边的配置类

这都是基本的配置类,网上随便就能抄到的。

@Configuration
@EnableAsync
public class ExecutorConfig {

    private static final Logger logger = LoggerFactory.getLogger(ExecutorConfig.class);

    @Bean
    public Executor asyncServiceExecutor() {
        logger.info("start asyncServiceExecutor");
        ThreadPoolTaskExecutor executor = new VisiableThreadPoolTaskExecutor();
        //配置核心线程数
        executor.setCorePoolSize(5);
        //配置最大线程数
        executor.setMaxPoolSize(5);
        //配置队列大小
        executor.setQueueCapacity(99999);
        //配置线程池中的线程的名称前缀
        executor.setThreadNamePrefix("async-service-");

        // rejection-policy:当pool已经达到max size的时候,如何处理新任务
        // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //执行初始化
        executor.initialize();
        return executor;
    }

}

一般情况下我们在学多线程的时候,都是Thread的匿名内部类写法和Runnable的重写run方法,但是在springboot中,为我们直接定义好了这相关操作,只需要annotation就可以了。

要知道,我们实际上去使用了多线程,达到的还是一种异步的操作,所以不多说了,上代码。

常规定义一个接口:
在这里插入图片描述
常规的去实现,在这里网上资料都会告诉你在Service层,接口的实现方法上扔一个@Async(< beanname >)
像这样:

因为是公司代码,就不多展示了,意思就是这个意思。@Async上参数写一个刚才配置类里面定义线程池参数的方法名。
在这里插入图片描述

然后控制层再引用一下跑,一般网上csdn的博客都这么说,日志还打印的不错,实际上postman一测试,啥东西也没有,就这样的:

在这里插入图片描述

没错,其实的确是执行了多线程,看了网上资料的话,也能感受到,但是异步执行的时候,这种方法,也就是Thread和Runnable多线程开发的这种方法,是没办法获取返回值的。

背了面试题的各位应该知道Callable接口可以返回线程中的返回值,我梳理一下它们之间的关系。
Runnable和Callable都可以进行多线程开发,Executor接口创建的线程池,是调度他们俩的容器,如果我们想要具体的获取值,是可以通过Future来实现的,但是,区别就在于Runnable使用了Future还是不能得到返回值,而Callable是可以的。

这里可以去看一下FutureTask的源码,里面是有Callable的,这里就不展开了。

言归正传,我们要是想获取返回值,就要通过Future来实现。

在这里插入图片描述

也就是说,我们最后返回一个Future对象给控制层,然后控制层这样:

在这里插入图片描述
就可以得到返回值了。

在这里插入图片描述

发布了296 篇原创文章 · 获赞 53 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_41936805/article/details/104273891