一.ThreadLocal是什么
JDK 1.2的版本中就提供java.lang.ThreadLocal,当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
ThreadLocal 数据的存储是使用了其静态内部类:ThreadLocalMap来存储数据。针对每个thread保留一个entry,如果对应的thread不存在则会调用initialValue。
ThreadLocal类接口很简单,只有4个方法,我们先来了解一下:
- void set(Object value)设置当前线程的线程局部变量的值。
- public Object get()该方法返回当前线程所对应的线程局部变量。
- public void remove()将当前线程局部变量的值删除,目的是为了减少内存的占用,该方法是JDK 5.0新增的方法。需要指出的是,当线程结束后,对应该线程的局部变量将自动被垃圾回收,所以显式调用该方法清除线程的局部变量并不是必须的操作,但它可以加快内存回收的速度。
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(); }
二.例子
package test1;
import java.util.HashMap;
public class TreadLocalTest {
static ThreadLocal<HashMap<Integer,Object>> TESTVAR = new ThreadLocal<HashMap<Integer,Object>>(){
@Override
protected HashMap<Integer,Object> initialValue() {
System.out.println(Thread.currentThread().getName()+"initialValue");
return new HashMap<Integer,Object>();
}
};
public static void main(String[] args){
Thread[] runs = new Thread[3];
for(int i=0;i<runs.length;i++){
runs[i]=new Thread(new TestTread(i));
}
for(int i=0;i<runs.length;i++){
runs[i].start();
}
}
}
class TestTread implements Runnable{
int thredNum;
public TestTread(int thredNum){
this.thredNum = thredNum;
}
public void run() {
System.out.println(Thread.currentThread().getName()+":start");
HashMap<Integer,Object> map = TreadLocalTest.TESTVAR.get();
for(int i=0;i<10;i++){
map.put(i, i+thredNum*10);
try{
Thread.sleep(100);
}catch(Exception ex){
}
}
System.out.println(Thread.currentThread().getName()+':'+map);
}
}