LocalThread分析

LocalThread源码分析:
一、首先看看LocalThread是干嘛的
外面能够看到的方法就以下四个:
get()  
protected  T initialValue() 。 
void remove()  
void set(T value)  
可以猜测这是一个管理集合的类。


二、再看看里面的一些方法
1.构造方法:空的,那就不管
2.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();
    }


简单的看就2步:
-得到当前的线程,并且调用getMap方法得到一个Map
-从Map中取,以当前对象this为key取。
ThreadLocalMap getMap(Thread t) {
		return t.threadLocals;
	}


传入Thread对象,得到他的threadLocals属性。
(看到这里才发现原来ThreadLocal与Thread都是java.lang包的,以前都没用过ThreadLocal,真是有点low了)
而且Thread和ThreadLocal的连接的非常紧密:在Thread中有一个ThreadLocalMap(ThreadLocal的内部类)属性,也就是上面的threadLocals属性,看来这都是设计好的。

再看看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;
	 }


首先是这个方法的调用时机:
在threadLocals为空或者其中没有key为this的value的时候调用,而且在Thread中看了一下也没找到给threadLocal赋值的操作,这个属性在Thread中好像就是专门给ThreadLocal留的。
那就先假想如果什么都没做,直接new出TheadLocal,调用get方法,那么这个时候走的是这个方法
再看看方法内部的执行:
首先调用initialValue方法,得到一个value,这个方法是protected,也就是需要子类重写的。
然后获取当前线程对应的那个ThreadLocalMap,然后判断map是否空,不是空,设置进去,这个简单。如果是空,则调用createMap,看方法名就是创建一个map的意思。
void createMap(Thread t, T firstValue) {
		t.threadLocals = new ThreadLocalMap(this, firstValue);
	}


这个方法也很简单,new出来一个ThreadLocalMap,传入2个参数。这里一行代码相当于做了两件事情:
1.new一个map
2.将key,value当做map的第一个键值对(这个map好像也就存一个键值对,后面再说)
最后返回的还是value,以前map中存的value或者说是initialValue返回的。


3.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);
	}	


这个方法应该很简单了,和setInitialValue干的事还简单。


4.remove:
 public void remove() {
         ThreadLocalMap m = getMap(Thread.currentThread());
         if (m != null)
             m.remove(this);
	}


看一下方法,一眼就能看懂


三、总结一下ThreadLocal的工作流程

总的来说就是一个集合管理器,如果当做是个黑盒子的话,可以就把他看成是一个map。
不同的线程都可以调用这个类的对象的set,get方法,因为里面用的是Thread.currentThread当做key,所以东西存在这里面不同的线程得到的是不一样的。
又因为set里面能传一个参数,即value,key默认为当前thread。get无参数,key同上,所以对于一个线程来说只能存放一个对象。
要想再存点,再new ThreadLocal把。
ThreadLocal管理的集合最大的好处就是相同的线程共享,不同的线程不干预。


四、使用ThreadLocal的优点

ThreadLocal它是jdk自带的,而且与Thread都在在java.lang包,两者的关系已经设计好(Thread中有个他的Map属性)。
其实优点就要归结于Thread中给的LocalThreadMap这个属性:
有了这个属性,每个线程独有一个Map,在get的时候,直接得到对应线程自己的map,再去里面取,不会涉及到任何的锁操作。效率高。


之前我也写过一个简单的TransactionManager,里面的Map也用于存放各线程的数据,不过他的key也是当前thread对象,所有的线程一起访问里面的资源就有可能发生资源共享问题,所以里面加了好多锁来控制。
在上一篇博客中不愿意用TransactionManager的原因也是这样,明明不复杂的东西,还要加几个锁,感觉好不舒服,现在发现ThreadLocal就能避免一些带来的问题,jdk他自己设计好的用起来就是方便。


五、个人的看法

既然Thread中提供了ThreadLocalMap,也有ThreadLocal来管理,那就用它没错。
如果没有提供,那自己写map再加锁管理应该也没错。


事件编程的时候以前给按钮写监听器,传入一个接口实现类的子对象,那时候觉得很神奇(怎么把这个方法放进去的?),也不知道其中的原理。
后来知道这个是靠回调实现的。
没有回调,方法就执行不了。


编程的时候有些时候就得留接口,留回调,这样后面处理起来就方便了。





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值