为什么需要ThreadLocal模式
来源:互联网 发布:匡恩网络 孙一桉 编辑:程序博客网 时间:2024/06/06 18:50
下面的变量都是指的引用变量。
如果我们在方法中要使用方法外的变量(不包括当前类或者父类的成员变量),有两种方式可以引用到方法外的变量:
1.方法传参。
2.将需要被引用的变量定义为类的静态变量。
两种方式都有弊端:方法传参的弊端是可能需要在很多地方传递这个参数(因为变量的存储和获取可能在不同的模块中);定义为类的静态变量则会引发线程安全问题。
为了解决以上两个问题,SUN公司的技术人员提出了ThreadLocal模式。存储变量时,ThreadLocal类会获取当前的线程对象Thread,并且把需要使用的变量(对象)存储到Thread的ThreadLocalMap中;获取变量时,ThreadLocal类会从当前线程对象Thread的ThreadLocalMap中去获取。这样既避免了参数传递,又不会引发线程安全问题。
下面贴出ThreadLocal的源码。
1.存储变量,ThreadLocal.set(value):
public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); }
首先会获取当前线程对象Thread,然后从Thread中取出ThreadLocalMap,ThreadLocal.getMap(thread):
ThreadLocalMap getMap(Thread t) { return t.threadLocals;}
如果当前的线程对象已经存在ThreadLocalMap,则存储变量;如果不存在,则先创建ThreadLocalMap,并且存储变量,ThreadLocal.createMap(thread, value):
void createMap(Thread t, T firstValue) { t.threadLocals = new ThreadLocalMap(this, firstValue);}
注意,这里是以ThreadLocal作为Key。
2.获取变量,ThreadLocal.get():
public T get() { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) return (T)e.value; } return setInitialValue(); }
先获取Thread对象,再从Thread中获取ThreadLocalMap。如果ThreadLocalMap存在,并且把当前的ThreadLocal对象作为Key获取到了Value,则返回Value,否则初始化ThreadLocalMap。ThreadLocal.setInitalValue():
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; }
ThreadLocal.initialValue()直接返回了null:
protected T initialValue() { return null; }
ThreadLocal模式提供一种在线程内共享变量(资源)的机制。但是ThreadLocal本身并不保证线程安全,所以如果要安全地使用ThreadLocal模式,共享变量必须是一个局部变量或者共享变量本身是线程安全的。
下面来看一个hibernate中典型的ThreadLocal的应用:
private static final ThreadLocal<Session> threadSession = new ThreadLocal<Session>(); public static Session getSession() throws InfrastructureException { Session s = threadSession.get(); try { if (s == null) { s = getSessionFactory().openSession(); threadSession.set(s); } } catch (HibernateException ex) { throw new InfrastructureException(ex); } return s; }
这里需要被共享的变量Session就是一个局部变量。
- 为什么需要ThreadLocal模式
- 我们为什么需要设计模式?
- 为什么需要Spring?--Spring中的设计模式
- ThreadLocal模式
- ThreadLocal模式
- ThreadLocal模式
- ThreadLocal模式
- ThreadLocal模式
- 标准模式和怪异模式:为什么需要DTD声明
- java的单例模式,为什么需要volatile
- struts2中的 ThreadLocal模式
- ThreadLocal 设计模式
- struts2中的 ThreadLocal模式
- Threadlocal设计模式
- ThreadLocal设计模式
- 简单ThreadLocal模式开发
- struts2中的ThreadLocal模式
- ThreadLocal模式探索
- Top 100 -- R包下载排名
- JavaMail中Session.getDefaultInstance的应用 | javax.mail.AuthenticationFailedException: 454 Error
- Android 仿微信QQ聊天界面
- CSS布局 ——从display,position, float属性谈起
- Java IO 技术之基本流类 ~~~~~~~~ (图+讲解+代码) 好好看 有好处
- 为什么需要ThreadLocal模式
- 图的邻接表存储 c实现
- Spring JDBCtemplate.batchupdate 批量跟新数据 实例
- 一次完整的Http请求过程
- 树莓派与Arduino串口通信
- Xamarin Android百度地图之Fragment做tab页加载百度地图
- 字符串的匹配
- 内存溢出
- 压力测试工具ab 及 centos下单独安装方法