threadlocal工作原理,threadlocal的作用和实现原理
ThreadLocal表示线程局部变量!那么什么是线程局部变量呢?这东西有什么用?有没有面试被问到说不出一二三的?今天就来看看这款产品的源代码,从根本上了解这款产品是做什么的。
如何解决写爬虫IP受阻的问题?立即使用。
Thread、ThreadLocalMap、Entry三者关系
其实他的源代码实现并没有想象中那么复杂。要点如下:
1.Java可以通过Thread.currentThread()获取Thread的当前实例对象。既然我们可以获得Thread对象实例,我们就可以操作它,比如为Thread对象设置一个值。
2.每个线程对象都有一个ThradLocalMap实例,它有一个条目数组。Entry对象有两个主要属性:value的弱引用和ThreadLocal,其中value属性是设置给当前线程的值,也是ThreadLocal的核心属性:
静态类入口扩展WeakReferenceThreadLocal?{
/**与此ThreadLocal关联的值。*/
对象值;
Entry(ThreadLocal?k,对象v) {
超(k);
值=v;
}
}注意Entry继承自WeakReference,其key为ThreadLocal object!(图1)
结合1和2两个知识点,我们可以知道,我们得到thread对象后,就可以操作当前Thread对象的ThreadLocalMap对象,然后把我们要保存的值赋给ThreadLocalMap的Entry的value属性。Thread、ThreadLocalMap、value、Value之间的关系可以如下图所示(图2):
从上图可以得出这样的结论:一个Thread对象持有一个ThreadLocalMap对象,然后,一个ThreadLoMap对象包含若干个ThreadLocal对象以及ThreadLocal对象所在线程的值!总之:一个线程对象可以保存多个ThreadLocal对象的变量值。
那么ThreadLocal和Thread有什么关系呢?他们如何读取值?下面根据源代码做一个简单的分析。
ThreadLocal和Thread的关联
先看ThreadLocal的set方法:
公共空集(T值){
//获取当前线程
thread t=thread . currentthread();
//获取当前线程持有的ThreadLocalMap
ThreadLocalThreadLocalMap map=get map(t);
//将值设置为threadlocalMap
如果(图!=空)
map.set(this,value);
其他
createMap(t,value);
}set方法很有逻辑,也很简单(结合上面的图2可以更好的理解J):
1.通过currentThread方法获取currentThread对象。
2.获取当前线程对象的ThreadLoalMap对象。
3.用值和ThreadLocal对象形成一个Entry对象,并将其保存在
在ThreadLoalMap的条目类型数组中。
在来看看ThreadLocal的get方法:
public T get() {
//获取当前线程
thread t=thread . currentthread();
//获取当前线程的ThreadLocalMap对象
ThreadLocalMap map=get map(t);
如果(图!=null) {
//获取要与ThreadLocal对象关联的值
ThreadLocalMap。entry e=map . get entry(this);
如果(e!=null) {
@SuppressWarnings(未选中)
//获取值
T结果=(T)e . value;
返回结果;
}
}
//null返回初始化值
返回setInitialValue();
}可以开发get的整体逻辑也很简单:
1.获取当前线程对象。
2.获取当前线程对象的ThreadLocalMap对象
3.从ThreadLocalMap中获取与ThreadLocal关联的Entry对象,特别是以ThreadLocal作为键。
4.在步骤3中获取条目的value属性并返回它。
通过整体观察get和set方法,可以得出以下结论:ThreadLocal对象调用set方法给Thread对象的ThreadLocalMap添加值;ThreadLocal对象调用get方法从thread对象的Threadlocal映射中获取值。核心是操纵Thread对象的ThreadLocalMap对象读写值。原理就是这么简单。
那么位于不同线程中的不同ThreadLocal对象与保存其他线程中的值有什么关系呢?下图可以清晰的描述出来:
ThreadLocal的使用实例
现在我们知道一个线程在Android中只有一个Looper对象,那么是怎么做到的呢?有效的是ThreadLocal。看看Looper的准备方法:
//定义静态ThreadLocal变量
static final threadlocal looper sThreadLocal=new threadlocal looper();
私有静态void准备(布尔quitAllowed) {
//一个线程只能与一个Looper对象相关联。
if (sThreadLocal.get()!=null) {
抛出新的RuntimeException(“每个线程只能创建一个循环”);
}
sthreadlocal . set(new Looper(quit allowed));
}通过观察prepare方法,可以通过sThreadLocal的get方法知道当前线程是否已经有Looper对象,如果有,抛出异常;如果当前线程没有设置Looper对象,调用ThreadLocal的set方法初始化Looper对象,并将其赋予当前线程:
sthreadlocal . set(new Looper(quit allowed));这确保了一个线程只有一个Looper对象。
至此,ThreadLocal的原理已经基本分析完毕。至于内部如何设置和获取,博主没有做太详细的分析,因为没必要。只要知道ThreadLocal的工作原因和使用场景就可以了。以上是ThreadLocal原理分析的详细内容。更多请关注我们的其他相关文章!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。