易语言可以做网站后端网站备案核验单怎么选

张小明 2026/1/8 8:52:58
易语言可以做网站后端,网站备案核验单怎么选,网络广告的发布方式包括,苏州 网站的公司哪家好前言在日常开发中#xff0c;我们经常会遇到需要在父子线程之间传递数据的场景。比如用户身份信息、请求ID、链路追踪ID等。ThreadLocal作为Java中重要的线程本地变量机制#xff0c;为我们提供了在单个线程内存储数据的便利。但是#xff0c;当涉及到父子线程之间的数据传递…前言在日常开发中我们经常会遇到需要在父子线程之间传递数据的场景。比如用户身份信息、请求ID、链路追踪ID等。ThreadLocal作为Java中重要的线程本地变量机制为我们提供了在单个线程内存储数据的便利。但是当涉及到父子线程之间的数据传递时ThreadLocal默认的行为并不能满足我们的需求。本文将介绍在SpringBoot应用中实现ThreadLocal父子线程传值的几种方式。ThreadLocal 基础回顾首先让我们简单回顾一下ThreadLocal的基本原理java public class ThreadLocalT { // 每个线程都有自己独立的ThreadLocalMap public void set(T value) { Thread t Thread.currentThread(); ThreadLocalMap map getMap(t); if (map ! null) map.set(this, value); else createMap(t, value); } public T get() { Thread t Thread.currentThread(); ThreadLocalMap map getMap(t); if (map ! null) { ThreadLocalMap.Entry e map.getEntry(this); if (e ! null) { SuppressWarnings(unchecked) T result (T)e.value; return result; } } return setInitialValue(); } }ThreadLocal的核心思想是为每个线程维护一个独立的ThreadLocalMap从而实现线程隔离。问题的提出让我们通过一个简单的例子来看看ThreadLocal在父子线程中的默认行为java public class ThreadLocalDemo { private static ThreadLocalString threadLocal new ThreadLocal(); public static void main(String[] args) { threadLocal.set(主线程的值); System.out.println(主线程获取: threadLocal.get()); // 输出: 主线程的值 Thread childThread new Thread(() - { System.out.println(子线程获取: threadLocal.get()); // 输出: null }); childThread.start(); } }从上面的例子可以看出子线程无法访问父线程中设置的ThreadLocal值。这是因为每个线程都有自己独立的ThreadLocalMap。解决方案一InheritableThreadLocalJava为我们提供了InheritableThreadLocal来解决父子线程传值的问题java public class InheritableThreadLocalDemo { private static InheritableThreadLocalString inheritableThreadLocal new InheritableThreadLocal(); public static void main(String[] args) { inheritableThreadLocal.set(主线程的值); System.out.println(主线程获取: inheritableThreadLocal.get()); Thread childThread new Thread(() - { System.out.println(子线程获取: inheritableThreadLocal.get()); // 输出: 主线程的值 }); childThread.start(); } }InheritableThreadLocal 原理分析InheritableThreadLocal的实现在Thread类中java public class Thread implements Runnable { // 父线程的inheritableThreadLocals会在创建子线程时复制 private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc, boolean inheritThreadLocals) { // ... if (inheritThreadLocals parent.inheritableThreadLocals ! null) this.inheritableThreadLocals ThreadLocal.createInheritedMap(parent.inheritableThreadLocals); // ... } }InheritableThreadLocal 的局限性1. 时机限制只在创建线程时进行值传递后续修改不会传递到已创建的子线程2. 线程池问题在线程池中使用时由于线程会被复用可能导致数据混乱解决方案二使用TransmittableThreadLocal阿里巴巴开源的TransmittableThreadLocalTTL是解决线程池场景下父子线程传值问题的优秀方案添加依赖xml dependency groupIdcom.alibaba/groupId artifactIdtransmittable-thread-local/artifactId version2.14.5/version /dependency基本使用java import com.alibaba.ttl.TransmittableThreadLocal; import com.alibaba.ttl.threadpool.TtlExecutors; public class TtlDemo { private static TransmittableThreadLocalString ttl new TransmittableThreadLocal(); public static void main(String[] args) { ttl.set(主线程的值); System.out.println(主线程获取: ttl.get()); // 使用TTL装饰的线程池 ExecutorService executor TtlExecutors.getTtlExecutorService( Executors.newFixedThreadPool(2) ); executor.submit(() - { System.out.println(线程池任务1获取: ttl.get()); // 输出: 主线程的值 }); // 修改值后提交新任务 ttl.set(更新后的值); executor.submit(() - { System.out.println(线程池任务2获取: ttl.get()); // 输出: 更新后的值 }); } }TTL 与Spring Boot的集成在Spring Boot应用中我们可以通过以下方式集成TTL1. 配置TTL异步执行器java Configuration EnableAsync public class AsyncConfig implements AsyncConfigurer { Override public Executor getAsyncExecutor() { ThreadPoolTaskExecutor executor new ThreadPoolTaskExecutor(); executor.setCorePoolSize(5); executor.setMaxPoolSize(10); executor.setQueueCapacity(100); executor.setThreadNamePrefix(Async-); // 使用TTL装饰 return TtlExecutors.getTtlExecutor(executor); } }2. 使用TTL的请求拦截器java Component public class TtlRequestInterceptor implements HandlerInterceptor { private static final TransmittableThreadLocalString requestId new TransmittableThreadLocal(); Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { String id UUID.randomUUID().toString(); requestId.set(id); return true; } Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { requestId.remove(); // 清理 } public static String getRequestId() { return requestId.get(); } }解决方案三自定义TaskDecoratorSpring提供了TaskDecorator接口允许我们对Runnable任务进行装饰java Configuration EnableAsync public class CustomAsyncConfig implements AsyncConfigurer { Override public Executor getAsyncExecutor() { ThreadPoolTaskExecutor executor new ThreadPoolTaskExecutor(); executor.setCorePoolSize(5); executor.setMaxPoolSize(10); executor.setQueueCapacity(100); executor.setThreadNamePrefix(CustomAsync-); // 设置自定义装饰器 executor.setTaskDecorator(new ContextCopyingDecorator()); executor.initialize(); return executor; } private static class ContextCopyingDecorator implements TaskDecorator { Override public Runnable decorate(Runnable runnable) { // 获取父线程的ThreadLocal上下文 MapString, Object context getContextFromCurrentThread(); return () - { try { // 在子线程中复制上下文 setContextToCurrentThread(context); runnable.run(); } finally { clearCurrentThreadContext(); } }; } private MapString, Object getContextFromCurrentThread() { MapString, Object context new HashMap(); // 收集当前线程的ThreadLocal值 // 例如从自定义的ThreadLocal中获取 if (UserContext.getUser() ! null) { context.put(userInfo, UserContext.getUser()); } if (RequestContextHolder.getRequestAttributes() ! null) { context.put(requestAttributes, RequestContextHolder.getRequestAttributes()); } return context; } private void setContextToCurrentThread(MapString, Object context) { // 在子线程中设置上下文 if (context.containsKey(userInfo)) { UserContext.setUser((UserContext.UserInfo) context.get(userInfo)); } if (context.containsKey(requestAttributes)) { RequestContextHolder.setRequestAttributes((RequestAttributes) context.get(requestAttributes)); } } private void clearCurrentThreadContext() { // 清理上下文防止内存泄漏 UserContext.clear(); RequestContextHolder.resetRequestAttributes(); } } }解决方案四使用Spring的RequestContextHolder在Spring Web应用中我们可以利用RequestContextHolder来传递请求上下文java Service public class ContextService { Async public CompletableFutureString asyncMethod() { // 获取父线程的请求上下文 RequestAttributes attributes RequestContextHolder.getRequestAttributes(); return CompletableFuture.supplyAsync(() - { // 在异步线程中设置上下文 RequestContextHolder.setRequestAttributes(attributes); try { // 执行业务逻辑 String result doSomeWork(); return result; } finally { RequestContextHolder.resetRequestAttributes(); } }); } private String doSomeWork() { // 获取请求相关的信息 HttpServletRequest request ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); return 处理完成: request.getRequestURI(); } }方案选择建议基于上述性能对比和适用场景我们可以给出以下选择建议1. 简单的父子线程传值使用InheritableThreadLocal2. 线程池场景推荐使用TransmittableThreadLocal3. Spring异步任务使用TaskDecorator4. Web应用请求上下文使用RequestContextHolder最佳实践1. 内存泄漏预防无论使用哪种方案都要注意及时清理ThreadLocaljava public class SafeThreadLocalUsage { private static ThreadLocalObject threadLocal new ThreadLocal(); public void doWork() { try { threadLocal.set(someValue); // 业务逻辑 } finally { threadLocal.remove(); // 防止内存泄漏 } } }2. 上下文封装建议封装一个统一的上下文管理器java public class UserContext { private static final ThreadLocalUserInfo USER_CONTEXT new TransmittableThreadLocal(); public static void setUser(UserInfo user) { USER_CONTEXT.set(user); } public static UserInfo getUser() { return USER_CONTEXT.get(); } public static void clear() { USER_CONTEXT.remove(); } public static class UserInfo { private String userId; private String userName; private String requestId; // getters and setters } }3. 拦截器统一管理java Component public class UserContextInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { UserInfo userInfo buildUserInfo(request); UserContext.setUser(userInfo); return true; } Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { UserContext.clear(); } private UserInfo buildUserInfo(HttpServletRequest request) { UserInfo userInfo new UserInfo(); userInfo.setUserId(request.getHeader(X-User-Id)); userInfo.setRequestId(UUID.randomUUID().toString()); return userInfo; } }总结本文介绍了四种在SpringBoot中实现ThreadLocal父子线程传值的方案1. InheritableThreadLocal最简单的原生解决方案适用于基础场景2. TransmittableThreadLocal功能强大的第三方解决方案特别适合线程池场景3. TaskDecoratorSpring提供的优雅解决方案集成度高4. RequestContextHolderSpring Web应用的内置方案在实际项目中我们应该根据具体的业务场景和技术栈选择合适的方案。同时要注意内存管理和上下文清理确保系统的稳定性和性能。
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

蓝海国际版网站建设软件技术安卓软件开发专业

Fabric框架:模块化AI提示工程的技术实践 【免费下载链接】fabric fabric 是个很实用的框架。它包含多种功能,像内容总结,能把长文提炼成简洁的 Markdown 格式;还有分析辩论、识别工作故事、解释数学概念等。源项目地址&#xff1a…

张小明 2026/1/7 6:40:03 网站建设

网站修改关键词不收录保定seo网站推广

在寻找理想的电子书阅读器时,Foliate以其优雅设计和强大功能脱颖而出。这款开源阅读器支持EPUB、PDF等多种格式,通过简洁界面和智能功能重新定义了数字阅读体验,让每个用户都能在Linux系统上享受沉浸式阅读时光。 【免费下载链接】foliate Re…

张小明 2026/1/7 6:39:28 网站建设

网站备案相关前置许可开发公司样板间的目的和意义

老年大学兴趣班:爷爷奶奶学会用AI给自己写诗 在杭州一所社区老年大学的教室里,80岁的张奶奶戴着老花镜,颤巍巍地在平板电脑上敲下一行字:“重阳登高望,儿孙满堂笑。”点击“生成”后几秒钟,一个熟悉的声音从…

张小明 2026/1/7 6:38:54 网站建设

个人接做网站多少钱做3d图的网站有哪些

深入Windows内核:手把手打造一个WDM虚拟串口驱动 你有没有遇到过这种情况——手头有一套老旧的工业控制软件,死死绑定在“COM3”上不放,可现在的笔记本连个RS-232接口都没有?或者你想测试一段串口通信协议,却苦于没有真…

张小明 2026/1/7 6:38:20 网站建设

家具做网站114黄页公司

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 创建一个Python脚本,使用COLAB环境,结合Kimi-K2模型自动生成数据处理代码。要求:1. 从CSV文件读取数据 2. 自动识别数据特征 3. 根据数据类型推…

张小明 2026/1/7 6:37:45 网站建设

重庆建设工程公司网站用word 做网站

Vim多文件编辑终极指南:用airline插件打造高效工作流 【免费下载链接】vim-airline 项目地址: https://gitcode.com/gh_mirrors/vim/vim-airline 还在为Vim中同时编辑多个文件而烦恼吗?每次都要输入复杂的命令来切换缓冲区,效率低下且…

张小明 2026/1/7 6:37:11 网站建设