1、ThreadLocal的使用
ThreadLocal的确是数据的隔离,但是并非数据的复制,而是在每一个线程中创建一个新的数据对象,然后每一个线程使用的是不一样的。
public class ThreadLocalTest {
private static ThreadLocal<Integer> threadLocal=new ThreadLocal<Integer>(){
@Override
protected Integer initialValue() {
return 0;
}
};
public Integer getNextStr() {
threadLocal.set(threadLocal.get()+1);
return threadLocal.get();
}
public static void main(String[] args) {
ThreadLocalTest local=new ThreadLocalTest();
MyThread myThread1=new MyThread(local);
MyThread myThread2=new MyThread(local);
MyThread myThread3=new MyThread(local);
myThread1.start();
myThread2.start();
myThread3.start();
}
private static class MyThread extends Thread{
private ThreadLocalTest tl;
public MyThread(ThreadLocalTest tl) {
this.tl = tl;
}
@Override
public void run() {
for (int i = 0; i < 3; i++) {
System.out.println(Thread.currentThread().getName()
+"::::"
+tl.getNextStr());
}
}
}
}
Thread-2::::1
Thread-1::::1
Thread-1::::2
Thread-1::::3
Thread-2::::2
Thread-2::::3
Thread-0::::1
Thread-0::::2
Thread-0::::3
这里可以看出,在每一个线程的确是没有互相影响
2、ThreadLocal的数据结构
ThreadLocal的数据结构如下:
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;
}
}
ThreadLocal内部有一个ThreadLocalMap,ThreadLocalMap
是ThreadLocal
的内部静态类,ThreadLocalMap的存储数据依赖成员变量Entry[]
,Entry继承WeakReference弱引用,存储方式为key-value
;接下来看一下ThreadLocal的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);
}
/* threadLocals为Thread类的成员变量*/
ThreadLocal.ThreadLocalMap threadLocals = null;
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
从上面的代码可以看出,使用ThreadLocalMap来存储数据时,key为当前的ThreadLocal对象,ThreadLocalMap为当前线程的threadLocals成员变量,如果ThreadLocalMap不为null,则直接更新value值;如果map为空,则将map初始化,并填充value值;