- 作用:存放每个线程自己私有的数据。
- 例子:
工具类
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package Thread;
import java.util.Date;
/**
*
* @author zjq
*/
public class LocalThread_tools {
public static ThreadLocal<Date> t1 = new ThreadLocal<Date>();
}
线程类
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package Thread;
import java.util.Date;
/**
*
* @author zjq
*/
public class LocalThreadA extends Thread{
@Override
synchronized public void run(){
try {
for(int i=0;i<20;i++){
if (LocalThread_tools.t1.get()==null) {
LocalThread_tools.t1.set(new Date());
}
System.out.println("A"+LocalThread_tools.t1.get().getTime());
Thread.sleep(100);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package Thread;
import java.util.Date;
/**
*
* @author zjq
*/
public class LocalThreadB extends Thread {
@Override
synchronized public void run() {
try {
for (int i = 0; i < 20; i++) {
if (LocalThread_tools.t1.get() == null) {
LocalThread_tools.t1.set(new Date());
}
System.out.println("B" + LocalThread_tools.t1.get().getTime());
Thread.sleep(100);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
LocalThreadA a = new LocalThreadA();
LocalThreadB b = new LocalThreadB();
a.start();
Thread.sleep(1000);
b.start();
}
}
- 结果
A1543414567634
A1543414567634
B1543414568632
A1543414567634
B1543414568632
A1543414567634
B1543414568632
........
可以看到a,b线程存在隔离性。为什么呢?
我们来看看源码
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
可以看到源码里的set()方法,首先获得了当前的线程,如果没有初始化过,就调用createMap初始化。初始化过程就是调用ThreadLocalMap的一个构造方法。ThreadLocalMap是干嘛用的?在看下ThreadLocalMap的源码。
ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
table = new Entry[INITIAL_CAPACITY];
int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
table[i] = new Entry(firstKey, firstValue);
size = 1;
setThreshold(INITIAL_CAPACITY);
}
方法中会定义一个Entry数组,初始化容量为16,扩容因子为2/3,Entry作为键值对存储,当前ThreadLocal对象为key,需要存储的对象为value。这样就实现了每个线程都有一个自己的“数据仓库”来存放自己的数据。