java.lang.ThreadLocal<T>
类,对它的调用在不同线程中有不同的结果。
1.使用场景
有些类不是线程安全的,若想在多线程下使用,我们可以为每个线程绑定一个此类的对象。
2.常用方法
T java.lang.ThreadLocal. get()返回当前线程所持有的对象。
void java.lang.ThreadLocal. set(T value)
设置当前线程所持有的对象。
void java.lang.ThreadLocal. remove()
移除当前线程所持有的对象。
3.例子
可见:线程安全
4.原理浅析
第一段,个人发挥。
//如果让我写,我会直接明了的实现
class ThreadLocalByYichu
{
hashmap
map=new HashMap<>();
T get(){
return map.get(Thread.currentThread());
}
}
//而JDK中把map放到了Thread中,并且key是ThreadLocal的实例,很个性。
class java.lang.Thread{
//思想是这样的,但由特殊的ThreadLocal.ThreadLocalMap实现。
Map
map;
}
第二段,摘自jdk。
/*
不同jdk版本,同一个类的实现可能作修改,以下信息对应于jre_1.8.0_111版本。
*/
class java.lang.Thread{
/* 依附于当前线程的ThreadLocal 的一些值,此字段只由 ThreadLocal这个类来维护. */
//注意这个ThreadLocal.ThreadLocalMap跟java.util.Map
一点关系都没有。
ThreadLocal.ThreadLocalMap threadLocals = null;
/*other fields and functions*/
}
class java.lang.ThreadLocal
{
//内部静态类
static class ThreadLocalMap{
//内部静态类的内部静态类
//当一个实例只被弱引用持有时,允许GC时被回收。这么设计防止ThreadLocalMap不必要的膨胀。
static class Entry extends WeakReference
> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal
k, Object v) {
super(k);
value = v;
}
}
/*other fields and functions*/
}
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
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();
}
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;
}
protected T initialValue() {
return null;
}
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
/*other fields and functions*/
}
5.知名框架如何用
springmvc就在用。
package org.springframework.web.context.request;
/**
* Holder class to expose the web request in the form of a thread-bound
* {@link RequestAttributes} object
* ...
*/
public abstract class RequestContextHolder {
private static final ThreadLocal<RequestAttributes> requestAttributesHolder;
/*other fields and functions*/
}