ThreadLocal原理和项目中如何使用
来源:互联网 发布:数据粒度和维度 编辑:程序博客网 时间:2024/04/30 16:40
本教程分如下三个部分
1. 项目中如何使用Threadlocal
2. Threadlocal和Thread关系以及Threadlocal源码分析
3. Threadlocal的DEMO练习(提供github和码云下载源代码)
首先上干货。讲讲我司项目中如何使用ThreadLocal。
这是一个登录会话保持的静态类,用来保存当前线程的登录信息。
使用AssertionContent原因:
由于通过ServletRequest request转换成
HttpServletRequest httpRequest = ( HttpServletRequest )request;
可以通过HttpSession session = httpRequest.getSession( false );
得到session。但是,并不是每个业务类或者方法都能得到当前的httpRequest。所以,就可以使用ThreadLocal在任何当前线程的任何业务类中,得到session。
在登录的filter中,可以通过session.setAttribute( BrowserSession.ASSERTION, bs );
将当前BrowserSession保存到会话中。
BrowserSession bs = new BrowserSession(); bs.setUid(userId); bs.setUname(name); ...
BrowserSession 是当前用户登录的一些个人信息。是业务自定义的实体类。
下一次再访问的时候,可以直接从session中得到用户所有信息。
在业务相关的filter中,
其中set方法如下:
public void setAttribute( String name, Object value ) { attributes.put( name, value ); }
以上set方法就是将session会话保存到AssertionContext
注意:此处是用一个AssertionContext中的一个Threadlocal变量保存了session。
所以在取session的时候,使用如下图所示方法:
其中AssertionContex.getContext()方法大致如下:
public static AssertionContext getContext() { AssertionContext context = contextHolder.get(); ... return context; }
其实也可以将以上步骤放到一个filter中,怎么顺手怎么使用。
接下来,就是在任何你想要使用session的地方,取得session,比如在业务service中:
其中checkLogin方法就是通过上面说到的先得到AssertionContext 中的Threadlocal再得到session来获得。
以上是讲解如何在业务中使用Threadlocal,下面结合源码介绍下原理:
Threadlocal设计两个java类:Thread和Threadlocal。
首先讲解下他们之间的关系
可以看到,Thread有个成员变量ThreadLocal.ThreadLocalMap,而ThreadLocalMap是Threadlocal的内部静态类。ThreadLocalMap中存的值的key为this,即当前Threadlocal类的引用,这样,每次从同一个Threadlocal和同一个Thread中得到的值就唯一确定了。
看一下Threadlocal的set方法:
public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); }
首先得到当前线程,然后得到当前线程的ThreadlocalMap。由于只要线程确定,所以map就确定。
getMap方法如下:
ThreadLocalMap getMap(Thread t) { return t.threadLocals; }
直接放回当前线程的成员变量。
可以看到第一次得到的map肯定为null,我们接下来看createMap方法:
void createMap(Thread t, T firstValue) { t.threadLocals = new ThreadLocalMap(this, firstValue); }
直接new了一个ThreadLocalMap,其中key为当前Threadlocal的引用。
如果map的值不为null则直接把值set到map中去。
看完set方法接着看get方法:
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(); }
首先,还是得到当前线程,得到当前线程的map,如果map不为空,则:
得到key为this的值,然后返回该值。如果map为空则调用setInitialValue方法
private T setInitialValue() { T value = initialValue(); Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); return value; }
继续判断map是否为空(这里再进行判断,我认为可能是在多个线程并发执行的情况下,如果执行到方法的入口处,其他的线程又new了一个ThreadlocalMap,辣么此处就不需要再new了),这里的initialValue()方法直接放回的是一个null。
到此,Threadlocal的set和get方法和原理都介绍完了。需要注意的是,由于ThreadlocalMap中的key是this引用,也就是说,this引用如果指向不同的对象,辣么通过get方法得到的值就不是希望得到的那个值。所以,要想每次得到的值都是正确的,必须使this指针指向的对象唯一,这就解释了为什么Threadlocal都使用静态变量来保存。
为了更好的理解Threadlocal的原理,下面有几个Threadlocal的demo练习,非常简单。大家可以clone下来或者fork下来试试。
git地址:
https://github.com/tengqingya/ThreadLocalPractice
码云地址:
https://git.oschina.net/tengqingya/ThreadLocalPractice
请尊重作者和版权,转载请标明出处。
联系作者:qq475804848,滕庆亚
- ThreadLocal原理和项目中如何使用
- threadLocal 原理与使用
- ThreadLocal使用及原理
- ThreadLocal使用、场景、原理
- ThreadLocal用法和原理
- 多线程编程之ThreadLocal的使用和内在原理
- 如何使用ThreadLocal变量
- ThreadLocal使用及原理解析
- ThreadLocal原理及使用场合
- ThreadLocal的使用与原理
- ThreadLocal用法和实现原理
- ThreadLocal用法和实现原理
- ThreadLocal用法和实现原理
- ThreadLocal用法和实现原理
- ThreadLocal用法和实现原理
- ThreadLocal用法和实现原理
- ThreadLocal用法和实现原理
- ThreadLocal用法和实现原理
- file_operation
- Spring BeanCopier深度复制
- EAP: unknown authentication type 26; Naking
- mysql的几种join
- 大数据工程师(开发)面试系列(3)
- ThreadLocal原理和项目中如何使用
- AR入门系列-06-Vuforia文字识别
- js 判断手机系统的方法
- SQL用and和or多表查询笛卡尔积
- 移动端高清多屏适配的解决方案
- 第一个progressive web application,发车!
- [LeetCode OJ]Longest Substring Without Repeating Characters
- jquery插件开发学习笔记(二)
- A-母牛的故事