真实项目中 ThreadLocal 的妙用

一、什么是 ThreadLocal

ThreadLocal 提供了线程的局部变量,每个线程都可以通过 set() 和 get() 来对这个局部变量进行操作,但不会和其他线程的局部变量冲突,实现了线程间的据隔离。

简单讲:一个获取用户的请求线程 A,如果向 ThreadLocal 填充变量 AValue(只能被线程 A 操作),该变量对其他获取用户的请求线程 B、C...是隔离的.

最简单的使用方式:

类似一次 HTTP 请求线程中,利用 ThreadLocal 存储 Cookie 对象,进行状态管理。set Cookie:

private ThreadLocal httpThreadLocal = new ThreadLocal();httpThreadLocal.set(“Cookie: sid=13420771402233”)

上面存储格式是 String ,实际场景存储的是具体的对象。在这次 HTTP 请求过程中,任何时候都可以获取 Cookie 。获取方式很简单 get Cookie:

String cookieValue = (String) httpThreadLocal.get();

Thread 与 ThreadLocal 对象引用关系图

二、你熟悉的场景

2.1 数据库连接池

比如一次请求线程进来,业务 Dao 需要更新 user 表和 user-detail 表。如果是 new 出两个数据库 Connection ,分别不同的 Connection 操作 user 表和 user-detail 表,就无法保证事务。那么数据库连接池是如何保证的?

答案是:利用 ThreadLocal 存储唯一 Connection 对象。每次请求线程,pool.getConnection 获取连接的时候都会这样操作:

  • 会从 ThreadLocal 获取 Connection 对象。如果有,则保证了后面多个数据库操作共用同一个 Connection ,从而保证了事务。
  • 如果没有,往 ThreadLocal 新增Connection 对象,并返回到线程
错误的做法
public class XXXService {private Connection conn;
}

因为 conn 是线程不安全的。这样会导致多个请求公用一个连接。请求量很大的情况下,延迟各种。你懂。

因此,使用 ThreadLocal 保证每个请求线程的 Connection 是唯一的。即每个线程有自己的连接。

继续讲到 Spring 框架,在事务开始时,会给当前线程一个Jdbc Connection,在整个事务过程,都是使用该线程绑定的connection来执行数据库操作,实现了事务的隔离性。Spring框架里面就是用的ThreadLocal来实现这种隔离

比如你访问百度、我访问百度,会有不同 Cookie 。而且你不能访问我的 Cookie,我也不能。顾名思义,使用 ThreadLocal 保证每个 HTTP 请求线程的 Cookie 是唯一的。

Cookie 这样才能做 Session 等状态管理。

三、实战场景

总结一下就是:ThreadLocal 可以让同一个线程中上下文之间数据共享

在上面章节 二、你熟悉的场景 其实介绍了很多现有场景。那么我这边具体的实战场景是什么?

简单的例子:

适用满足这两个条件的场景:1.每个线程独有的一些信息,2.这些信息又会在多个方法或类中用到。

  1. 一个请求线程,里面有两个异步小线程,各有一个方法。分别处理 A 或 B 业务
  2. 一种方法是传递不可变的入参
  3. 另一种就是 ThreadLocal,放在 ThreadLocal 的入参,会被各个方法共享。而且多个请求线程互不影响
复杂的例子:

一次发货操作:会根据入参,进行组件化、流程编排话。那么入参会被各个地方用到,而且有些流程组件是异步的(类似 new thread 操作的)。这时候可以定一个 XXContext 上下文:

public class XXContext {private static ThreadLocal<Map<Class<?>, Object>> context = new InheritableThreadLocal<>();/*** 把参数设置到上下文的Map中*/public static void put(Object obj) {Map<Class<?>, Object> map = context.get();if (map == null) {map = new HashMap<>();context.set(map);}if (obj instanceof Enum) {map.put(obj.getClass().getSuperclass(), obj);} else {map.put(obj.getClass(), obj);}}/*** 从上下文中,根据类名取出参数*/@SuppressWarnings("unchecked")public static <T> T get(Class<T> c) {Map<Class<?>, Object> map = context.get();if (map == null) {return null;}return (T) map.get(c);}/*** 清空ThreadLocal的数据*/public static void clean() {context.remove();}
}

代码解析:

  • 都是 static 操作,类似 DateUtil 玩法
  • 记得每次请求线程后清理。可以 AOP 去清理,加个注解就行。因为同一个请求线程可能被业务方公用。

(完)

file

转载于:https://www.cnblogs.com/Alandre/p/11145516.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/247626.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

css之flex布局

flex布局是css3中的重要布局方式&#xff0c;称为“弹性布局”&#xff0c;每次想到它主要是遇到元素垂直居中、元素宽高自适应的问题&#xff0c;这些问题在flex中都能过简单设置就解决&#xff0c;它更像是原生APP中的布局操作&#xff0c;布局不必写N多的盒模型代码来实现&a…

javascript对URL中的参数进行简单加密处理

javascript的api本来就支持Base64&#xff0c;因此我们可以很方便的来进行编码和解码。 var encodeData window.btoa("namexiaoming&age10")//编码 var decodeData window.atob(encodeData)//解码。 下面来个具体的例子来说明如何对url中参数进行转码&#xff…

HTML元素title里面如何换行

在调试代码的时候我就遇到一个问题&#xff0c;HTML元素title里面通常只显示一行&#xff0c;那我想要他换行&#xff0c;就是多行显示&#xff0c;如何实现&#xff1f;JS代码里面比如Alert里面又该如何换行&#xff1f; 经过我的一番实验 要实现这种效果有几种方法&#xff0…

div内图片和文字水平垂直居中

大小不固定的图片、多行文字的水平垂直居中 本文综述 想必写css的都知道如何让单行文字在高度固定的容器内垂直居中&#xff0c;但是您知道或者想过让行数不固定的文字在高度固定的容器内垂直居中呢&#xff1f;本文将会告诉你如何实现多行文字的垂直居中显示。 关于图片垂直居…

敏友的【敏捷个人】有感(3): 有感于“敏捷个人”讨论与练习

2010年我对个人管理进行了自己的一些思考&#xff0c;在2011年提出敏捷个人概念&#xff0c;并且在线上、线下进行了多次交流&#xff0c;在一些大会上也做过分享。现在&#xff0c;已经有很 多IT和非IT的敏友们知道并在践行敏捷个人&#xff0c;帮助自己更快的成长。我收到大家…

jQuery编写插件

引言&#xff1a; 在项目中不同页面经常要用到已经写好的交互&#xff0c;比如弹窗&#xff0c;比如下拉菜单&#xff0c;比如选项卡&#xff0c;比如删除... 此时如果每次都把代码copy一份无疑是一件比较麻烦并且无趣的事情&#xff0c;而且个人认为有些low了&#xff0c;我们…

webstorm中nodejs代码提示

preferences->languages&frameworks->Node.js and Npm中选择一个本地的node版本 preferences->languages&frameworks->JavaScript->Libraries 勾选node.js Core 回到代码

Array.prototype.slice.call(arguments)

Array.prototype.slice.call(arguments)能将具有length属性的对象转成数组&#xff0c;除了IE下的节点集合&#xff08;因为ie下的dom对象是以com对象的形式实现的&#xff0c;js对象与com对象不能进行转换&#xff09;如&#xff1a;1 var a{length:2,0:first,1:second}; 2 Ar…

nodejs常用模块-url

URL nodejs中针对url的常用方法。 node下打印url&#xff0c;结果&#xff1a; 引入url模块 var url require(url) 1、parse方法 将url解析成对象&#xff0c;parse方法原型&#xff1a; url.parse(urlStr[, parseQueryString][, slashesDenoteHost]) 可传递三个参数…

常用的javascript设计模式

请坚持 什么是设计模式 百度百科&#xff1a; 设计模式&#xff08;Design pattern&#xff09;是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。 使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问&#xff0c;设计模式…

iOS警告-This block declaration is not a prototype

关于警告 我们定义一个不带参数的block,通常是如下的方式 1typedefvoid (^UpdateSwichBtnBlock)();在xcode9中会提示一个警告 12This block declaration is not a prototypeInsert ‘void解决方式可以是如下的几种 1typedefvoid (^UpdateSwichBtnBlock)(void);但是这样,很多第三…

mongoose操作mongodb

http://mongoosejs.com/docs/api.html#index-js mongoose是nodejs环境下操作mongodb的模块封装&#xff0c;使用mongoose之后&#xff0c;实际上只需要在mongodb中创建好数据库与用户&#xff0c;集合的定义、创建、操作等直接使用mongoose即可。 一、连接二、重要概念三、基本…

mac下iterm配色、半透明与样式设置

主要为了实现命令行颜色高亮与整个命令窗口半透明效果。 1、配色主题包下载 1、http://iterm2colorschemes.com/ 下载后解压&#xff0c;到iterm2中&#xff0c;左上角iTerm2->preferences->Profiles&#xff0c;右侧面板找到Colors选项&#xff0c;右下角展开Color Pr…

一个 Dubbo 服务启动要两个小时

前几天在测试环境碰到一个非常奇怪的与 dubbo 相关的问题&#xff0c;事后我在网上搜索了一圈并没有发现类似的帖子或文章&#xff0c;于是便有了这篇。 希望对还未碰到或正在碰到的朋友有所帮助。 现象 现象是这样的&#xff0c;有一天测试在测试环境重新部署一个 dubbo 应用的…

表单提交enctype参数详解之:application/x-www-form-urlencode和multipart/form-data

application/x-www-form-urlencode 我们在提交表单的时候&#xff0c;form表单参数中会有一个enctype的参数。enctype指定了HTTP请求的Content-Type。 默认情况下&#xff0c;HTML的form表单的enctypeapplication/x-www-form-urlencoded。 application/x-www-form-urlencoded是…

内网端口映射工具

由于开发微信需要一个公网域名&#xff0c;需要将本地端口映射到外网域名&#xff0c;最热的工具是ngrok&#xff0c;但被微信屏蔽了&#xff0c;这里使用的是natapp&#xff0c;环境是mac&#xff0c;windows下可使用nat123、花生壳等工具实现同样功能。 简单记录一下过程。 …

iOS----------iPhone导出手机所有短信

第一步&#xff1a;手机连接到itunes 选择本电脑备份 备份的时候不要加密 然后立即备份 第二步&#xff1a;前往文件夹&#xff0c;找到itunes的备份路径~/Library/Application Support/MobileSync/Backup 在这目录下搜索 3d0d开头的文件&#xff0c;这就是 iPhone 短信的…

跨站点脚本(XSS)

1. 简介 跨站点脚本(XSS)是当前web应用中最危险和最普遍的漏洞之一。安全研究人员在大部分最受欢迎的网站,包括Google, Facebook, Amazon, PayPal等网站都发现这个漏洞。如果你密切关注bug赏金计划,会发现报道最多的问题属于XSS。为了避免跨站脚本,浏览器也有自己的过滤器,但安…

CSRF攻击原理及防御

CSRF攻击原理及防御 一、CSRF攻击原理 CSRF是什么呢&#xff1f;CSRF全名是Cross-site request forgery&#xff0c;是一种对网站的恶意利用&#xff0c;CSRF比XSS更具危险性。想要深入理解CSRF的攻击特性我们有必要了解一下网站session的工作原理。   session我想大家都不…

H3C FTP配置示例

转载于:https://www.cnblogs.com/fanweisheng/p/11156596.html