您的位置:首页 > 移动开发 > Android开发

Android多线程之ThreadLocal

2016-07-06 00:11 417 查看

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的我的浅显的理解,希望对看到这篇文章的人能有所增益,同时这也是方便我自己理解,加强记忆,如有纰漏之处还望指正!

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息