您的位置:首页 > 编程语言 > Java开发

Java并发(三) ThreadLocal关键字

2016-05-09 17:17 531 查看
TheadLocal称为线程本地存储,就是说一个变量,每个线程都有它的一个副本,并且相互之间是独立的。

ThreadLocal类的实现

下面是该类的提供的关键的几个方法:

public T get() { }
public void set(T value) { }
public void remove() { }
protected T initialValue() { }


通过查看jdk中该类的源码,可以大致看到上述方法的实现,其中:

/**
* Returns the value in the current thread's copy of this
* thread-local variable.  If the variable has no value for the
* current thread, it is first initialized to the value returned
* by an invocation of the {@link #initialValue} method.
*
* @return the current thread's value of this thread-local
*/
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();
}


是get()方法的实现,首先是通过一个getMap得到ThreadLocalMap,然后在这个ThreadLocalMap中通过this来获得对应的值作为返回值:如果将ThreadLocalMap看作map的话,我们可以发现实际上这个map的key是当前的ThreadLoca变量。

接下来看getMap方法的实现

/**
* Get the map associated with a ThreadLocal. Overridden in
* InheritableThreadLocal.
*
* @param  t the current thread
* @return the map
*/
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}


实际上就是返回了线程t的成员变量threadLocals,该变量是一个ThreadLocalMap类型。

这样我们就可以总结出TheadLocal大致的工作原理:有依附于每个线程的一个ThreadLocalMap的类似map的数据结构,这个数据结构的key就是我们定义的ThreadLocal变量,同时我们可以定义多个ThreadLocal变量作为这个map的key。

用图形表示为:



从这里来看,ThreadLocal其实只是相当于声明了某种类型是线程本地存储,实际上的数据是存储在每个Thread实例的成员变量中的。这也就是线程本地存储名称的来源—数据实际上存储在本地线程中。

另外还有set:

/**
* Sets the current thread's copy of this thread-local variable
* to the specified value.  Most subclasses will have no need to
* override this method, relying solely on the {@link #initialValue}
* method to set the values of thread-locals.
*
* @param value the value to be stored in the current thread's copy of
*        this thread-local.
*/
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}


用于修改value值。

另外注意到,ThreadLocalMap中的内部类Entry是声明为WeakReference,这是java中的四种Reference类型之一。通过相关相关书籍和网页,简单介绍一下:

StrongReference,就是我们通常通过new Object()这样的形式得到的引用,叫强引用,只要强引用还在,GC就不会回收相应的对象。

SoftReference,软引用,系统在内存将要溢出之前,会对这类引用的对象进行清理。比如外部数据源:文件、数据库、网络等可声明为该类型引用。

WeakReference,弱引用,被弱引用关联的对象如果被JVM识别为弱可达,那么在下次GC的时候就会进行回收。

SoftReference与WeakReference的区别是GC的时间是尽量推迟的。

Phantom,虚引用。不能通过虚引用来获得一个对象实例,唯一的目的是在对象被回收时得到一个系统通知。

ThreadLocal应用场景

数据库连接、Session管理等
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java jdk 线程