1.概述
- 线程的局部变量, 每个线程自己独立隔离开来,线程之间的数据不共享,所以不会有数据安全性问题.
- ThreadLocal,很多地方叫做线程本地变量,也有些地方叫做线程本地存储,其实意思差不多。ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。
2.示例
public class ThreadLocalTest {
private ThreadLocal<Integer> count = new ThreadLocal<Integer>() {
protected Integer initialValue() {
return new Integer(0);
};
};
public int getNext() {
Integer value = count.get();
value++;
count.set(value);
return value;
}
public static void main(String[] args) {
ThreadLocalTest threadLocalTest = new ThreadLocalTest();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
System.out.println(Thread.currentThread().getName() + " " + threadLocalTest.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() + " " + threadLocalTest.getNext());
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
3.ThreadLocal源码简析
public class ThreadLocal<T> {
//1.获取值
public T get() {
Thread t = Thread.currentThread(); //当前线程
ThreadLocalMap map = getMap(t); //当前线程是否在ThreadLocalMap中
if (map != null) { //如有ThreadLocalMap,则取值
ThreadLocalMap.Entry e = map.getEntry(this);//entry是map中的组(包含key和value)
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
//为空,返回初始值结果
return setInitialValue();
}
//2.设置值
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
//3.去掉值
public void remove() {
ThreadLocalMap m = getMap(Thread.currentThread());
if (m != null)
m.remove(this);
}
//4.设置初始值
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;
}
//5.获取map中的值,将绑定到Thread的threadLocals中.
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
//6.创建一个createMap
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
//ThreadLocal的内部类ThreadLocalMap,将key(线程)和值存在Entry中
static class ThreadLocalMap {
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
private void set(ThreadLocal<?> key, Object value) {
....
}
private void remove(ThreadLocal<?> key) {
....
}
private Entry getEntry(ThreadLocal<?> key) {
}
}
}
//Thread中有ThreadLocal.ThreadLocalMap,存的是thread真正的值
public class Thread implements Runnable {
ThreadLocal.ThreadLocalMap threadLocals = null;
}
- 将当前线程和当前线程计算的值保存到ThreadLocalMap对象的Entry中(ThreadLocal为key,value为值),
- 而ThreadLocalMap对象又存在放当前Thread类下的ThreadLocal.ThreadLocalMap中.
取值的时候到当前线程中取ThreadLocal.ThreadLocalMap的Entry响应的值就可以了.
Entry(ThreadLocal,Object)=>Entry存到ThreadLocalMap下=>Thread.ThreadLocal.ThreadLocalMap 存储了 ThreadLocalMap