java get请求传参_Java-ThreadLocal三种使用场景
ThreadLocal对于每一位Java读者而言我想可能都不陌生,因为面试基本都会被问到。
Java-ThreadLocal三种使用场景
关于ThreadLocal
JDK1.2的版本中就提供java.lang.ThreadLocal类,每一个ThreadLocal能够放一个线程级别的变量, 它本身能够被多个线程共享使用,并且又能够达到线程安全的目的,且绝对线程安全。
ThreadLocal包含了四个方法:
void set(Object value)设置当前线程的线程局部变量的值。public Object get()该方法返回当前线程所对应的线程局部变量。public void remove()将当前线程局部变量的值删除,其目的是为了减少内存使用,加快内存回收。protected Object initialValue()返回该线程局部变量的初始值,该方法是一个protected的方法,目的是为了让子类覆盖而设计的。
在实际的工作中,我们在哪些场景下会用到ThreadLocal呢?这里笔者整理了三个使用场景。
场景一:代替参数的显式传递
当我们在写API接口的时候,通常Controller层会接受来自前端的入参,当这个接口功能比较复杂的时候,可能我们调用的Service层内部还调用了 很多其他的很多方法,通常情况下,我们会在每个调用的方法上加上需要传递的参数。
但是如果我们将参数存入ThreadLocal中,那么就不用显式的传递参数了,而是只需要ThreadLocal中获取即可。
这个场景其实使用的比较少,一方面显式传参比较容易理解,另一方面我们可以将多个参数封装为对象去传递。
场景二:全局存储用户信息
在现在的系统设计中,前后端分离已基本成为常态,分离之后如何获取用户信息就成了一件麻烦事,通常在用户登录后, 用户信息会保存在Session或者Token中。 这个时候,我们如果使用常规的手段去获取用户信息会很费劲,拿Session来说,我们要在接口参数中加上HttpServletRequest对象,然后调用 getSession方法,且每一个需要用户信息的接口都要加上这个参数,才能获取Session,这样实现就很麻烦了。
在实际的系统设计中,我们肯定不会采用上面所说的这种方式,而是使用ThreadLocal,我们会选择在拦截器的业务中, 获取到保存的用户信息,然后存入ThreadLocal,那么当前线程在任何地方如果需要拿到用户信息都可以使用ThreadLocal的get()方法 (异步程序中ThreadLocal是不可靠的)
对于笔者而言,这个场景使用的比较多,当用户登录后,会将用户信息存入Token中返回前端,当用户调用需要授权的接口时,需要在header中携带 Token,然后拦截器中解析Token,获取用户信息,调用自定义的类(AuthNHolder)存入ThreadLocal中,当请求结束的时候,将ThreadLocal存储数据清空, 中间的过程无需在关注如何获取用户信息,只需要使用工具类的get方法即可。
public class AuthNHolder {private static final ThreadLocal> loginThreadLocal = new ThreadLocal>();public static void map(Map map){loginThreadLocal.set(map);}public static String userId(){ return get("userId");}public static String get(String key){ Map map = getMap(); return map.get(key); }public static void clear(){ loginThreadLocal.remove();}}
场景三:解决线程安全问题
在Spring的Web项目中,我们通常会将业务分为Controller层,Service层,Dao层, 我们都知道@Autowired注解默认使用单例模式,那么不同请求线程进来之后,由于Dao层使用单例,那么负责数据库连接的Connection也只有一个, 如果每个请求线程都去连接数据库,那么就会造成线程不安全的问题,Spring是如何解决这个问题的呢?
在Spring项目中Dao层中装配的Connection肯定是线程安全的,其解决方案就是采用ThreadLocal方法,当每个请求线程使用Connection的时候, 都会从ThreadLocal获取一次,如果为null,说明没有进行过数据库连接,连接后存入ThreadLocal中,如此一来,每一个请求线程都保存有一份 自己的Connection。于是便解决了线程安全问题
ThreadLocal在设计之初就是为解决并发问题而提供一种方案,每个线程维护一份自己的数据,达到线程隔离的效果。
慎用的场景
1.线程池中线程调用使用ThreadLocal 由于线程池中对线程管理都是採用线程复用的方法。在线程池中线程非常难结束甚至于永远不会结束。 这将意味着线程持续的时间将不可预測,甚至与JVM的生命周期一致
2.异步程序中,ThreadLocal的參数传递是不靠谱的, 由于线程将请求发送后。就不再等待远程返回结果继续向下运行了,真正的返回结果得到后,处理的线程可能是其他的线程。Java8中的并发流也要考虑这种情况
3.使用完ThreadLocal ,最好手动调用 remove() 方法,防止出现内存溢出,因为中使用的key为ThreadLocal的弱引用, 如果ThreadLocal 没有被外部强引用的情况下,在垃圾回收的时候会被清理掉的,但是如果value是强引用,不会被清理, 这样一来就会出现 key 为 null 的 value。
java get请求传参_Java-ThreadLocal三种使用场景相关推荐
- java持久层用文件_JAVA中用三种方法将字符串持久化到文件中
经常需要将数据进行持久化,而我们的文件系统是最古老也是最可靠的保存方式.这里就给出一个在JAVA中把字符串保存到文件中的例子.如下: package test.base; import java.io ...
- java 运行class 传参_JAVA 不同Class传值问题
展开全部 可以通过构62616964757a686964616fe4b893e5b19e31333365663431造方法传递给 B, 如下:import java.awt.*; import jav ...
- java调用c传参_JAVA 调用C 语言程序,并且进行传参收结果等操作
import java.io.*; import java.lang.*; class test3{ public static void main(String []args) throws IOE ...
- java循环嵌套语句示范_java的三种循环结构与循环嵌套
循环结构: 语法,及执行顺序 语法: while(boolean类型){ //功能语句 } 执行顺序: 1断小括号中的值是否为true,如果为true,执行功能语句 2行完功能语句,继续判断小括号中的 ...
- shell脚本触发java程序支持传参补跑_01
文章目录 一.java程序 1. 创建java项目 2. 创建包结构 3. 创建java类 4. 编译 5. 编译后的包结构总览 二.shell脚本 2.1. 创建基础目录 2.2. 上传项目到指定目 ...
- C语言与java中函数传参比较
C语言与java中函数传参比较 首先先说结论:C语言中参数传递有值传递,地址传递,引用传递.但java中的参数传递只有值传递 1.C语言中的参数传递 1>值传递 值传递非常好理解,其实就是对函数 ...
- scrapy实现post请求与请求传参
不推荐使用scrapy框架发送post请求,配置复杂,如果在数据量大 的情况下,可以通过如下代码来实现: import scrapyclass FySpider(scrapy.Spider):name ...
- 18-爬虫之scrapy框架请求传参实现的深度爬取(全站爬取)05
请求传参实现的深度爬取 深度爬取:爬取的数据没有在同一张页面中(首页数据+详情页数据) 在scrapy中如果没有请求传参我们是无法进行持久化存储数据的 实现方式: scrapy.Request(url ...
- 爬虫开发10.scrapy框架之日志等级和请求传参
今日概要 日志等级 请求传参 今日详情 一.Scrapy的日志等级 - 在使用scrapy crawl spiderFileName运行程序时,在终端里打印输出的就是scrapy的日志信息. - 日志 ...
最新文章
- Udacity机器人软件工程师课程笔记(三十六) - GraphSLAM
- WebAssembly Studio:Mozilla提供的WASM工具
- iOS学习笔记2-微博cell界面的实现
- 在ubuntu中安装minicom时出现device /dev/tty8 is locked解决办法
- JavaScript浮点运算0.2+0.1 !== 0.3
- C/C++中预编译#,##,#error作用
- 无线 iphone客户端测试白皮书(二)
- 为Eclipse安装功能扩展插件
- JS中浮点数运算误差处理
- Webpack 2 视频教程 009 - 配置 ESLint 实现代码规范自动测试 (上)
- 93. 复原IP地址
- 抓包工具——【Mac】Charles的下载和安装
- JAVA调用海康威视SDK
- 虚拟化试题1-网络和存储
- Sketch 54.1 Shark 鲨鱼中文汉化特别版 Mac 设计师必备的原型UI设计工具
- 目标检测经典论文——YOLOv3论文翻译:YOLOv3: An Incremental Improvement(YOLOv3:增量式的改进)
- NOIP 2006 金明的预算方案 (裸?)分组背包
- ddr2代内存最大升级到多少_DDR2台式内存条单条最大多少G?
- 《Mysql必知必会》-----笔记(2)
- 对List进行多维度排序