当前位置: 首页 > wzjs >正文

如何自己做电影网站北京网站开发培训

如何自己做电影网站,北京网站开发培训,遨游网站建设,搞笑视频素材网站免费1.TransmittableThreadLocal简介 com.alibaba.ttl.TransmittableThreadLocal(简称 TTL)是阿里巴巴开源的一个工具类,旨在解决 ThreadLocal 在线程池中无法传递上下文变量 的问题。它是对 InheritableThreadLocal 的增强,尤其适用…

1.TransmittableThreadLocal简介

com.alibaba.ttl.TransmittableThreadLocal(简称 TTL)是阿里巴巴开源的一个工具类,旨在解决 ThreadLocal 在线程池中无法传递上下文变量 的问题。它是对 InheritableThreadLocal 的增强,尤其适用于异步编程、线程池任务调度等场景。


1.1 核心功能

  1. 上下文传递:在普通线程池中,ThreadLocal 的值不会自动传递到新线程。TransmittableThreadLocal 通过 任务包装机制,将主线程的上下文变量传递到子线程(如线程池中的线程)中。

  2. 兼容性:它兼容 ThreadLocal 和 InheritableThreadLocal 的行为,同时支持 Java 8+ 的异步编程模型(如 CompletableFutureForkJoinPool 等)。

  3. 生命周期管理:支持在任务执行前后自动绑定/解绑上下文,避免内存泄漏。


1.2 典型使用场景

  • 分布式追踪(如 SkyWalking、Zipkin):在异步调用链中传递 Trace ID。
  • 日志上下文(如 MDC):在异步任务中保留请求标识(如用户 ID、请求 ID)。
  • 事务传播:在线程池中传递事务上下文(如 Seata 分布式事务)。
  • 权限验证:在异步任务中传递用户身份信息。

2.TransmittableThreadLocal基本用法

step1.引入依赖

<!-- Maven -->
<dependency><groupId>com.alibaba</groupId><artifactId>transmittable-thread-local</artifactId><version>2.12.1</version> <!-- 使用最新版本 -->
</dependency>

step2. 定义 TransmittableThreadLocal

import com.alibaba.ttl.TransmittableThreadLocal;public class Context {private static final TransmittableThreadLocal<String> CONTEXT = new TransmittableThreadLocal<>();public static void set(String value) {CONTEXT.set(value);}public static String get() {return CONTEXT.get();}
}

step3. 各种用法

import com.alibaba.ttl.TtlRunnable;ExecutorService executor = Executors.newFixedThreadPool(2);
// 主线程设置上下文
Context.set("Hello TTL");// 提交任务前包装 Runnable
// TtlRunnable 是 Runnable 的任务包装器
executor.submit(TtlRunnable.get(() -> {System.out.println("子线程: " + Context.get());
}, true)); // 第二个参数表示是否复制上下文//使用 TtlCallable 包装 Future 任务
// TtlCallable 是 Callable 的任务包装器
Future<String> future = executor.submit(TtlCallable.get(() -> {return "Result with context: " + Context.get();
}));//使用于 CompletableFuture
CompletableFuture.runAsync(TtlRunnable.get(() -> {System.out.println("CompletableFuture: " + Context.get());
}, true), executor);//如果使用自定义线程池,建议通过 TtlExecutors 包装:
Executor ttlExecutor = TtlExecutors.getTtlExecutorService(Executors.newFixedThreadPool(5));

关键特性

1. 自动传播:如果线程池本身是 TTL 兼容的(如使用 TtlExecutors 包装),则无需手动包装任务。

2. 线程池改造:如果使用自定义线程池,建议通过 TtlExecutors 包装:

ExecutorService ttlExecutor = TtlExecutors.getTtlExecutorService(Executors.newFixedThreadPool(2));

3. 清除机制:需要显式调用 remove() 避免内存泄漏:

try {Context.set("value");// 执行任务
} finally {Context.remove();
}

3. TransmittableThreadLocal实现上下文传递-完整demo

3.1 场景说明:

有一个“查询用户成绩”场景,需要将用户上下文(如用户ID、租户信息、AccessKey、Locale)在 Controller、Service 层甚至异步调用中传递。

3.2 实现目标

  • 用户请求进入系统后,从请求头中提取上下文信息。
  • 上下文信息在整个请求链路中自动传递,包括异步调用。
  • 上下文信息不会被多个请求交叉污染。
  • 上下文信息在请求结束后自动清理。

3.3 代码

step1. 定义用户上下文(UserContext)

import com.alibaba.ttl.TransmittableThreadLocal;
import lombok.Builder;
import lombok.Data;@Data
@Builder
public class UserContext {private static final TransmittableThreadLocal<UserContext> USER_CONTEXT= new TransmittableThreadLocal<UserContext>(){@Overrideprotected UserContext initialValue() {return new UserContext();}};/*** 用户ID*/private String userId;/*** 租户ID*/private String tenantId;/*** 访问密钥*/private String accessKey;/*** 语言*/private String locale;public UserContext() {}public UserContext(String userId, String tenantId, String accessKey, String locale) {this.userId = userId;this.tenantId = tenantId;this.accessKey = accessKey;this.locale = locale;}public static UserContext get() {return USER_CONTEXT.get();}public static void set(UserContext userContext) {USER_CONTEXT.set(userContext);}public static void remove() {USER_CONTEXT.remove();}}

step2. 配置拦截器(注入上下文UserContext)

定义一个UserContextInterceptor拦截器,用于从request Header中获取用户信息:

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;public class UserContextInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {// 从请求头中提取用户信息(示例)String userId = request.getHeader("Custom-User-Id");String tenantId = request.getHeader("Custom-Tenant-Id");String accessKey = request.getHeader("Custom-Access-Key");String locale = request.getHeader("Custom-Accept-Language");// 设置用户信息UserContext userContext = UserContext.builder().userId(userId).tenantId(tenantId).accessKey(accessKey).locale(locale).build();UserContext.set(userContext);return true;}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception {// 务必在请求结束时清理上下文,避免内存泄漏UserContext.remove();}
}

注册UserContextInterceptor拦截器:

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class UserContextWebConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new UserContextInterceptor()).addPathPatterns("/**");}
}

step3.在 Service 层使用上下文(UserContext)

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import com.alibaba.ttl.threadpool.TtlExecutors;
import org.springframework.stereotype.Service;@Service
public class ScoreService {//配置异步线程池(使用 TtlExecutors),用于测试多线程场景下,子线程也能获取到主线程的上下文信息private Executor taskExecutor = TtlExecutors.getTtlExecutorService(Executors.newFixedThreadPool(5));public void queryScore() {String userId = UserContext.get().getUserId();String tenantId = UserContext.get().getTenantId();String accessKey = UserContext.get().getAccessKey();String locale = UserContext.get().getLocale();System.out.println("Sync start ====== ");System.out.println("current thead: " + Thread.currentThread().getName());System.out.println("Sync: Querying score for user: " + userId + ", tenant: " + tenantId +" accessKey: " + accessKey + ", locale: " + locale);}//多线程场景下,子线程也能获取到主线程的上下文信息public void queryScoreAsync() {taskExecutor.execute(() -> {String userId = UserContext.get().getUserId();String tenantId = UserContext.get().getTenantId();String accessKey = UserContext.get().getAccessKey();String locale = UserContext.get().getLocale();System.out.println("ASync start ====== ");System.out.println("current thead: " + Thread.currentThread().getName());System.out.println("Async: Querying score for user: " + userId + ", tenant: " + tenantId +" accessKey: " + accessKey + ", locale: " + locale);});}
}

step4. Controller层

@RestController
public class ScoreController {@Autowiredprivate ScoreService scoreService;@GetMapping("ScoreController/queryScore")public String queryScore() {scoreService.queryScore();scoreService.queryScoreAsync();return "ScoreController queryScore success!";}@GetMapping("ScoreController/hello")public String hello() {return "ScoreController say hello";}
}

step5.测试

启动应用后,在postman中做测试。

case1: 不设置Header,UserContext获取的值为null:

case2: 设置Header,UserContext获取的值为设置的值:

case3:使用 ThreadLocal 做对比测试,新建的子线程中无法获取到UserContext设置的值

将UserContext.USER_CONTEXT设置为 ThreadLocal:

@Data
@Builder
public class UserContext {//private static final TransmittableThreadLocal<UserContext> USER_CONTEXT//    = new TransmittableThreadLocal<UserContext>(){//    @Override//    protected UserContext initialValue() {//        return new UserContext();//    }//};// 改用 ThreadLocal,其他代码不变private static final ThreadLocal<UserContext> USER_CONTEXT = new ThreadLocal<UserContext>(){@Overrideprotected UserContext initialValue() {return new UserContext();}};
}

设置Header后,发送请求,新建的子线程中无法获取到UserContext设置的值:


文章转载自:

http://Nopue4zP.jydhL.cn
http://B1DIvOTs.jydhL.cn
http://wfWCR7uJ.jydhL.cn
http://6xsayiw9.jydhL.cn
http://paU8LP7E.jydhL.cn
http://7y0dQKPN.jydhL.cn
http://YF8Krp9q.jydhL.cn
http://0f5FLeqf.jydhL.cn
http://p5AFq6ZS.jydhL.cn
http://jCe05IY3.jydhL.cn
http://5DOGWs83.jydhL.cn
http://64PgJ2Vh.jydhL.cn
http://BaqyFE81.jydhL.cn
http://zJne5mDD.jydhL.cn
http://um9aXzu2.jydhL.cn
http://EWXxLYsZ.jydhL.cn
http://ndgPXl69.jydhL.cn
http://CYLpYJEW.jydhL.cn
http://jL5ohZxc.jydhL.cn
http://scVFhJ3e.jydhL.cn
http://XW88jQGm.jydhL.cn
http://UMBRBRoZ.jydhL.cn
http://HWDcNRSb.jydhL.cn
http://mocUK8AF.jydhL.cn
http://xC3YkFeD.jydhL.cn
http://sfuZikDI.jydhL.cn
http://J2B08UKh.jydhL.cn
http://BRae9JDM.jydhL.cn
http://IVI5xpbX.jydhL.cn
http://r2nSu6mA.jydhL.cn
http://www.dtcms.com/wzjs/779600.html

相关文章:

  • 网站建设厂家电子商务网站建设与实践考试
  • 宠物网站设计与制作电子商务网站建设asp
  • 图书馆网站建设汇报深圳万户网络技术有限公司
  • 烟台建站软件设计图ai生成
  • 10个奇怪又有趣的网站电商网站开发公司杭州
  • 网站需要多少钱免费企业网站开发
  • 代做网站优化aws 虚机wordpress教程
  • 莆田市荔城区建设局网站wordpress 注入
  • 建设局网站打不开是什么原因自己做视频网站有点卡
  • js音乐网站模板wordpress怎么上传插件
  • 山东三强建设咨询有限公司网站中国建设工程网站投标
  • 广西住房和城乡建设局官网北京网站优化公司 卓立海创
  • 在网站做专题上海百度seo网站优化
  • 深圳企业网站建设开发费用邓州建网站
  • 商业性质网站设计做网站用什么空间
  • 中英网站模板 照明做免费导航网站
  • 南京网站设计个人网络推广常见的方法
  • 免费域名申请网站空间网站运营管理的内容有哪些
  • 做论坛网站多少钱高密做网站哪家强价位
  • 黑彩网站开发大连设计网站的公司
  • 织梦网站如何修改数据库配置做app需要什么技术
  • 网站建设与管理赚钱吗做外贸网站一般多少钱
  • 网络空间 网站 域名古镇免费网站建设
  • 网站建设综合案例设计图片素材网站有哪些
  • 专项培训网站建设方案动易的网站能否静态
  • 哪个网站可以免费做国外网站企业网站404页面设计
  • 同一个空间可以做两个网站么上海专业的网站建设公司排名
  • 响应式 企业网站商城网页
  • 做网站网页的人是不是思维页面设计
  • 更改了网站关键词后要怎么做小程序制作公司排行