ThreadLocal:
代码演示:
package com.roocon.thread.tb3;
public class Demo {
private ThreadLocal<Integer> count = new ThreadLocal<Integer>() {
protected Integer initialValue() {
return new Integer(0);//这个要初始化不然为null
};
};
public int getNext() {
Integer value = count.get();
value++;
count.set(value);
return value;
}
public static void main(String[] args) {
Demo d = new Demo();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
System.out.println(Thread.currentThread().getName() + " " + d.getNext());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
System.out.println(Thread.currentThread().getName() + " " + d.getNext());
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
public int getNext() {
Integer value = count.get();
value++;
count.set(value);
return value;
}
注意这里的get和set也是去线程的ThreadLocalMap的Entry找当前的threadlocal为key的vaule,找不到用当前的Threadlocal实例的初始值。
ThreadLocal.ThreadLocalMap threadLocals = null;
ThreadLocalMap 是ThreadLocal里面的内部类,里面是有个内部类:
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
getMap:
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
get
public T get() {
Thread t = Thread.currentThread();//获得当前的线程
ThreadLocalMap map = getMap(t);//返回当前线程的ThreadLocalMap
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);//根据当前的ThreadLocal,就是new的那个,获取ThreadLocalMap.Entry
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;//返回Entry的value
return result;
}
}
return setInitialValue();
}
getEntry方法,一个线程可以有多个Entry的。key就是当前的Threadlocal:
private Entry getEntry(ThreadLocal<?> key) {
int i = key.threadLocalHashCode & (table.length - 1);//找到Entry数组的Entry
Entry e = table[i];
if (e != null && e.get() == key)
return e;
else
return getEntryAfterMiss(key, i, e);
}
每一个
getMap这个是Thread类里面的
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
这个是Thread类里面的
ThreadLocal.ThreadLocalMap threadLocals = null;
其中ThreadLocalMap是ThreadLocal的静态内部类,里面是Entry或者是Entry数组。
getMap找到Thread里面的
内部的:
这个是为什么我们可以获得Entry的原因
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
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;
}
这个就是返回null
protected T initialValue() {
return null;
}
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();
}
Entry类型其中k是ThreadLocal<?>的。
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
总结:Thread里面有一个对ThreadLocalMap的引用,内部是Entry,key是ThrealLocal。
再次总结:每个Thread里面有一个ThreadLocakMap里面是很多的Entry,每个Entry的key是ThreadLocal实例,value是值。
set
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t); //获得t的ThreadLocalMap
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
remove
public void remove() {
ThreadLocalMap m = getMap(Thread.currentThread());
if (m != null)
m.remove(this);
}
----------------------
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);
}
----------------
remove方法 当前的threadLocal是Key
public void remove() {
ThreadLocalMap m = getMap(Thread.currentThread());
if (m != null)
m.remove(this);
}
--------------------------------------tb3-------------------------------------------------