SpringBoot进阶:4招优雅实现SpringBoot异步线程间数据传递

本文介绍了四种在SpringBoot中优雅地实现在异步线程间传递数据的方法,包括手动设置、线程池设置TaskDecorator、InheritableThreadLocal和TransmittableThreadLocal。推荐使用TaskDecorator结合线程池或TransmittableThreadLocal来避免手动设置和内存泄漏问题。
摘要由CSDN通过智能技术生成

Spring Boot 自定义线程池实现异步开发相信看过陈某的文章都了解,但是在实际开发中需要在父子线程之间传递一些数据,比如用户信息,链路信息等等

比如用户登录信息使用ThreadLocal存放保证线程隔离,代码如下:

 
 

/** * @author 公众号:码猿技术专栏 * @description 用户上下文信息 */ public class OauthContext { private static final ThreadLocal<LoginVal> loginValThreadLocal=new ThreadLocal<>(); public static LoginVal get(){ return loginValThreadLocal.get(); } public static void set(LoginVal loginVal){ loginValThreadLocal.set(loginVal); } public static void clear(){ loginValThreadLocal.remove(); } }

那么子线程想要获取这个LoginVal如何做呢?

今天就来介绍几种优雅的方式实现Spring Boot 内部的父子线程的数据传递。

编辑切换为居中

添加图片注释,不超过 140 字(可选)

1. 手动设置

每执行一次异步线程都要分为两步:

  1. 获取父线程的LoginVal

  2. 将LoginVal设置到子线程,达到复用

代码如下:

 
 

public void handlerAsync() { //1. 获取父线程的loginVal LoginVal loginVal = OauthContext.get(); log.info("父线程的值:{}",OauthContext.get()); CompletableFuture.runAsync(()->{ //2. 设置子线程的值,复用 OauthContext.set(loginVal); log.info("子线程的值:{}",OauthContext.get()); }); }

虽然能够实现目的,但是每次开异步线程都需要手动设置,重复代码太多,看了头疼,你认为优雅吗?

2. 线程池设置TaskDecorator

TaskDecorator是什么?官方api的大致意思:这是一个执行回调方法的装饰器,主要应用于传递上下文,或者提供任务的监控/统计信息。

知道有这么一个东西,如何去使用?

TaskDecorator是一个接口,首先需要去实现它,代码如下:

 
 

/** * @author 公众号:码猿技术专栏 * @description 上下文装饰器 */ public class ContextTaskDecorator implements TaskDecorator { @Override public Runnable decorate(Runnable runnable) { //获取父线程的loginVal LoginVal loginVal = OauthContext.get(); return () -> { try { // 将主线程的请求信息,设置到子线程中 OauthContext.set(loginVal); // 执行子线程,这一步不要忘了 runnable.run(); } finally { // 线程结束,清空这些信息,否则可能造成内存泄漏 OauthContext.clear(); } }; } }

这里我只是设置了LoginVal,实际开发中其他的共享数据,比如SecurityContext,RequestAttributes....

TaskDecorator需要结合线程池使用,实际开发中异步线程建议使用线程池,只需要在对应的线程池配置一下,代码如下:

 
 

@Bean("taskExecutor") public ThreadPoolTaskExecutor taskExecutor() { ThreadPoolTaskExecutor poolTaskExecutor = new ThreadPoolTaskExecutor(); poolTaskExecutor.setCorePoolSize(xx); poolTaskExecutor.setMaxPoolSize(xx); // 设置线程活跃时间(秒) poolTaskExecutor.setKeepAliveSeconds(xx); // 设置队列容量 poolTaskExecutor.setQueueCapacity(xx); //设置TaskDecorator,用于解决父子线程间的数据复用 poolTaskExecutor.setTaskDecorator(new ContextTaskDecorator()); poolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 等待所有任务结束后再关闭线程池 poolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true); return poolTaskExecutor; }

此时业务代码就不需

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值