ThreadLocal简介
ThreadLocal实现的是线程的数据的本地存储,同一个ThreadLocal对象在不同的线程中都有自己的值,所有的线程共享同一个ThreadLocal对象,但是每一个访问它的线程都存储这个线程自己的值,并且一个线程改变了这个ThreadLocal对象的值但是并不能改变其他线程中ThreadLocal的值。ThreadLocal允许赋值为null。
ThreadLocal的主要方法
ThreadLocal的主要方法有set()方法,顾名思义,是对ThreadLocal进行赋值,get()方法则是取出当前线程中ThreadLocal的值,记住每一个线程中取出的值只是当前线程中之前所赋值。我们可以看一下ThreadLocal中的源码:
public void set(T value) {
Thread currentThread = Thread.currentThread();
Values values = values(currentThread);
if (values == null) {
values = initializeValues(currentThread);
}
values.put(this, value);
}
上述源码中我们可以看到set()方法所存储的值存放在了Values中,这个values是什么呢?我们可以接着看下一段源码:
static class Values {
private static final int INITIAL_SIZE = 16;
private static final Object TOMBSTONE = new Object();
private Object[] table;
private int mask;
private int size;
private int tombstones;
private int maximumLoad;
private int clean;
Values() {
initializeTable(INITIAL_SIZE);
this.size = 0;
this.tombstones = 0;
}
Values(Values fromParent) {
this.table = fromParent.table.clone();
this.mask = fromParent.mask;
this.size = fromParent.size;
this.tombstones = fromParent.tombstones;
this.maximumLoad = fromParent.maximumLoad;
this.clean = fromParent.clean;
inheritValues(fromParent);
}
@SuppressWarnings({"unchecked"})
private void inheritValues(Values fromParent) {
Object[] table = this.table;
for (int i = table.length - 2; i >= 0; i -= 2) {
Object k = table[i];
if (k == null || k == TOMBSTONE) {
continue;
}
tombstones and references.
Reference<InheritableThreadLocal<?>> reference
= (Reference<InheritableThreadLocal<?>>) k;
Object below.
InheritableThreadLocal key = reference.get();
if (key != null) {
table[i + 1] = key.childValue(fromParent.table[i + 1]);
} else {
// The key was reclaimed.
table[i] = TOMBSTONE;
table[i + 1] = null;
fromParent.table[i] = TOMBSTONE;
fromParent.table[i + 1] = null;
tombstones++;
fromParent.tombstones++;
size--;
fromParent.size--;
}
}
}
我们可以看到这个values是个静态内部类,其中的inheritValues方法我们可以看到我们存储的值实际上都是存放在了Object数组里。而get()方法我们可以看一下:
public T get() {
// Optimized for the fast path.
Thread currentThread = Thread.currentThread();
Values values = values(currentThread);
if (values != null) {
Object[] table = values.table;
int index = hash & values.mask;
if (this.reference == table[index]) {
return (T) table[index + 1];
}
} else {
values = initializeValues(currentThread);
}
return (T) values.getAfterMiss(this);
}
源码中的描述很清晰,我们的值所在object数组中的索引实际就是index+1。还有remove()方法,这里remove()方法就不做详加解释,相信大家看名字亦能理解。
ThreadLocal的一个实现示例
这里写一个小的例子,帮助大家理解一下ThreadLocal:
mFutureTest = new FutureTest();
mFutureTest.test();
mThreadLocal = new ThreadLocal<Integer>();
new Thread("thread_one"){
@Override
public void run() {
mThreadLocal.set(1);
Log.i("threadloacl","thread_one======"+mThreadLocal.get());
}
}.start();
new Thread("thread_two"){
@Override
public void run() {
mThreadLocal.set(2);
Log.i("threadloacl","thread_two======"+mThreadLocal.get());
}
}.start();
Log.i("threadlocal","mainthread="+mThreadLocal.get());
运行结果:
I/threadlocal: mainthread=null
I/threadloacl: thread_one======1
I/threadloacl: thread_two======2
这里在主线程中并没有赋值,所以主线程中的值为null。这就是关于ThreadLocal的我的浅显的理解,希望对看到这篇文章的人能有所增益,同时这也是方便我自己理解,加强记忆,如有纰漏之处还望指正!