Thread类中相关代码如下:
1.每个Thread实例中都存储各自ThreadLocal.ThreadLocalMap实例。所以各线程间不会共享资源
2.线程中的ThreadLocalMap变量的值是在ThreadLocal实例进行get或者set操作时创建的
3.ThreadLocal.ThreadLocalMap中,key是ThreadLocal实例,value就是需要存储的值
至少完成了两个方面的数据的隔离:
纵向----线程与线程之间访问各自的ThreadLocalMap实例
横向----同一个线程中,ThreadLocalMap实例中,不同的ThreadLocal实例为key映射不同的value
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
这个实例变量,只有在exit()方法中,才被使用,将其赋值为null。
ThreadLocal类中相关代码如下
/**
* 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)
return (T)e.value;
}
return setInitialValue();
}
/**
* 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);
}
/**
* 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;
}
/**
* Create the map associated with a ThreadLocal. Overridden in
* InheritableThreadLocal.
*
* @param t the current thread
* @param firstValue value for the initial entry of the map
* @param map the map to store.
*/
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
/**
* ThreadLocalMap is a customized hash map suitable only for
* maintaining thread local values. No operations are exported
* outside of the ThreadLocal class. The class is package private to
* allow declaration of fields in class Thread. To help deal with
* very large and long-lived usages, the hash table entries use
* WeakReferences for keys. However, since reference queues are not
* used, stale entries are guaranteed to be removed only when
* the table starts running out of space.
*/
static class ThreadLocalMap {
.....
}
1.每个Thread实例中都存储各自ThreadLocal.ThreadLocalMap实例。所以各线程间不会共享资源
2.线程中的ThreadLocalMap变量的值是在ThreadLocal实例进行get或者set操作时创建的
3.ThreadLocal.ThreadLocalMap中,key是ThreadLocal实例,value就是需要存储的值
至少完成了两个方面的数据的隔离:
纵向----线程与线程之间访问各自的ThreadLocalMap实例
横向----同一个线程中,ThreadLocalMap实例中,不同的ThreadLocal实例为key映射不同的value
在上面的代码中,ThreadLocalMap是ThreadLocal的嵌套类(这样其实我们完全可以将他们看做两个独立的类,只不过相互之间可以访问私有成员)。
(1)在代码任何位置都可以获得当前的Thread实例;
(2)Thread只是持有ThreadLocalMap实例,且不会对其做任何有用的操作;不会持有ThreadLocal实例
(3)ThreadLocalMap的操作在ThreadLocal的方法中,所以需要有ThreadLocal的实例来完成,ThreadLocal实例可以获取当前执行线程的实例进而获取ThreadLocalMap实例,然后以自身为key进行存取操作
所以要使用ThreadLocal,最关键的就是创建一个任何地方都可以访问到的ThreadLocal实例。这个实例需要在整个线程运行期间都可以获取得到特定的ThreadLocal实例,这样才能保证以该实例为key来保存的那个值可以在线程运行期间可以始终获取的到
1.在我们的应用类中,添加一个ThreadLocal类型的静态实例变量,代码如下
public class ThreadTest
{
public static void main(String args[])
{
Task2 t2 = new Task2();
for (int i = 0; i< 4;i ++)
{
Thread t = new Thread(t2);
t.start();
}
}
}
class Task1 implements Runnable
{
private static ThreadLocal<Integer> countTL = new ThreadLocal<Integer>(){
protected synchronized Integer initialValue(){
return 10;}
};
public Integer get(){
return countTL.get();
}
public void set(Integer value){
countTL.set(value);
}
public void run()
{
set(0);
for (int i = 0;i < 10;i++)
{
set(get() + 1);
System.out.println(Thread.currentThread().getName() + "||" + get());
}
}
}
class Task2 implements Runnable
{
private static int a = 0;
public void run()
{
for (int i = 0;i < 10;i++)
{
a = a + 1;
System.out.println(Thread.currentThread().getName() + "||" + a);
}
}
}