1. ThreadLocal原理
ThreadLocal为每个线程创建一个对象副本,将对象共享转变为对象“独有”,从而避免多线程对象共享的问题,每个线程都可以独立的读写对象,而对其他线程没有影响。
ThreadLocal内部有一个ThreadLocalMap内部类,用于维持线程本地变量。下面是ThreadLocal get()方法源代码:
public T get() {
//获取当前执行线程
Thread t = Thread.currentThread();
//取得当前线程的ThreadLocalMap实例
ThreadLocalMap map = getMap(t);
if (map != null) {
//map以当前对象实例为key
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null)
return (T)e.value;
}
//返回初始值
return setInitialValue();
}
从上面的源代码可以看出 get()该方法返回当前线程所对应的线程所持有的对象。ThreadLocal的其他:
void set(Object value)设置当前线程的线程局部变量的值。
public void remove()将当前线程局部变量的值删除,目的是为了减少内存的占用
protected Object initialValue()返回该线程局部变量的初始值, setInitialValue()方法返回的就是initialValue()设置的初始值。
2.ThreadLocal实例
package thread;
import org.junit.Test;
public class ThreadLocalTest {
public final ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>(){
@Override
protected Integer initialValue() {
return 0;
}
};
@Test
public void threadLocaltest() {
for (int i = 0; i < 5; i++) {
new Thread(new Runnable() {
@Override
public void run() {
Integer sum = threadLocal.get();
for (int j = 1; j <10; j++) {
sum=sum+j;
}
threadLocal.set(sum);
System.out.println(Thread.currentThread().getName()+": "+ threadLocal.get());
};
}).start();
}
}
}
结果为:
Thread-0 : 45
Thread-1 : 45
Thread-2 : 45
Thread-3 : 45
Thread-4 : 45
说明ThreadLocal可以使各个线程独自拥有一个变量副本,互不影响,从而实现对象访问的线程安全。
3. ThreadLocal与同步机制的比较
同步机制是多线程共享一个变量,只是访问时通过锁使得同一个时间内只有一个线程可以访问变量,将并发访问转化为串行访问,是以时间换空间。
而ThreadLocal则是为每个线程创建一个变量副本,这里不再是多个线程之间的共享,是以空间换时间,并发性比同步机制要好。ThreadLocal提供了线程安全的共享对象方式,可以把不安全的变量封装进ThreadLocal实现线程安全。