ThreadLocal学习

在JDK中有对ThreadLocal的如下描述的。

该类提供了线程局部 (thread-local) 变量。这些变量不同于它们的普通对应物,因为访问某个变量(通过其 get 或 set 方法)的每个线程都有自己的局部变量,它独立于变量的初始化副本。

什么叫每个线程都有自己的局部变量,这些局部变量拿来做什么?ThreadLocal怎么使每个线程都有自己的局部变量,带着这些疑问,通过查百度,看源码,终于弄懂了。且看下文。

以下文章摘自http://baike.baidu.com/view/4498010.htm

ThreadLocal 的使用  
 使用方法一:   
Hibernate的文档时看到了关于使ThreadLocal管理多线程访问的部分。具体代码如下
1. public static final ThreadLocal session = new ThreadLocal(); 
2. public static Session currentSession() {  
3. Session s = (Session)session.get();  
4. //open a new session,if this session has none  
5. if(s == null){   
6. s = sessionFactory.openSession();   
7. session.set(s);   
8. }   return s;   
9. } 
我们逐行分析  
1。 初始化一个ThreadLocal对象,ThreadLocal有三个成员方法 get()、set()、initialvalue()。   如果不初始化initialvalue,则initialvalue返回null。 
3。session的get根据当前线程返回其对应的线程内部变量,也就是我们需要的net.sf.hibernate.Session(相当于对应每个数据库连接).多线程情况下共享数据库链接是不安全的。ThreadLocal保证了每个线程都有自己的s(数据库连接)。 
5。如果是该线程初次访问,自然,s(数据库连接)会是null,接着创建一个Session,具体就是行6。  
6。创建一个数据库连接实例 s   
7。保存该数据库连接s到ThreadLocal中。   
8。如果当前线程已经访问过数据库了,则从session中get()就可以获取该线程上次获取过的连接实例。 
逐行分析中 “session的get根据当前线程返回其对应的线程内部变量”
我们来看看ThreadLocal的get方法

 public T get() {
        Thread t = Thread.currentThread();//获取当前线程
        ThreadLocalMap map = getMap(t);//获取当前线程的ThreadLocalMap
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);//this为当前ThreadLocal
            if (e != null)
                return (T)e.value;//拿出当前ThreadLocal存储的值,
        }
        return setInitialValue();
    }
每个线程都会自带一个ThreadLocalMap,ThreadLocalMap是一个 key(ThreadLocal)/value(T)的建值对,
通过线程的ThreadLocalMap,一个线程可以保存多个ThreadLocal以及要存储的值,ThreadLocalMap中含有线程自己的独立副本,使线程可以独立地改变自己的副本,而不会和其它线程的副本冲突。
例如有一个用户登录功能,当A用户登录时,会启动一个线程ta,把他的用户名,密码等信息保存在ta线程的以ThreadLocal为key的ThreadLocalMap中
当B用户来登录时,会令启一个线程tb,再把B用户的用户名,密码等信息保存在tb线程的以ThreadLocal为key的ThreadLocalMap中,因而A、B两用户的信息放在不同的线程中,每个线程都有自己的副本,两者不会冲突
实现以上的功能只需要几句代码:
ThreadLocal<User> local;
local.set(new User("A",....));
获取各自的信息也很简单
User user = (User)local.get();
J2ee中的Seesion中有关于会话的一些操作,当启动一个会话时,每个会话中都可能会存有用户的一些信息,用户名、购物车等等,每一个会话之间的这些信息相互之间是互相独立的,
修改各自会话中的信息也都是相互独立了,这一点和ThreadLocal的用法相吻合。
虽然没有看过Session会话的实现原理,猜测Session的实现也许也会用到ThreadLocal的这些思想。
继续来看看其他的各种方法吧。

getMap方法如下

getMap方法如下
    ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }
	ThreadLocalMap.Entry 是一个WeakReference<ThreadLocal>,WeakReference是弱引用对象,当程序需要资源时会释放WeakReference所引用的对象,这里指ThreadLocal
	 static class Entry extends WeakReference<ThreadLocal> {
            /** The value associated with this ThreadLocal. */
            Object value;

            Entry(ThreadLocal k, Object v) {
                super(k);
                value = v;
            }
        }
我们来看看ThreadLocal的set方法
    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);//以当前ThreadLocal为key,Value为值放入ThreadLocalMap中
        else
            createMap(t, value);//如果当前线程没有ThreadLocalMap则创建
    }
    createMap 为:

void createMap(Thread t, T firstValue) {
	t.threadLocals = new ThreadLocalMap(this, firstValue);
}





  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值