最近查看Android,Looper源碼的時(shí)候,看到一個(gè)這樣的寫(xiě)法
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
給我的第一印象是:
1.比較懶的一種單例的寫(xiě)法娶耍。
2.跟線程有很大的關(guān)系朴爬。不然怎么會(huì)叫做ThreadLocal呢局待?
3.覺(jué)得是一種集合,因?yàn)樘峁┝薵et/set方法。 但是本身是單例机断,那么get出來(lái)不是同一個(gè)值嗎?那不就是沒(méi)有意義了嗎材部?帶著這些問(wèn)題查看了一下源碼毫缆。
public class ThreadLocal<T> {
/* Thanks to Josh Bloch and Doug Lea for code reviews and impl advice. */
/**
* Creates a new thread-local variable.
*/
public ThreadLocal() {}
/**
* Returns the value of this variable for the current thread. If an entry
* doesn't yet exist for this variable on this thread, this method will
* create an entry, populating the value with the result of
* {@link #initialValue()}.
*
* @return the current value of the variable for the calling thread.
*/
@SuppressWarnings("unchecked")
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);
}
/**
* Provides the initial value of this variable for the current thread.
* The default implementation returns {@code null}.
*
* @return the initial value of the variable.
*/
protected T initialValue() {
return null;
}
/**
* Sets the value of this variable for the current thread. If set to
* {@code null}, the value will be set to null and the underlying entry will
* still be present.
*
* @param value the new value of the variable for the caller thread.
*/
public void set(T value) {
Thread currentThread = Thread.currentThread();
Values values = values(currentThread);
if (values == null) {
values = initializeValues(currentThread);
}
values.put(this, value);
}
/**
* Removes the entry for this variable in the current thread. If this call
* is followed by a {@link #get()} before a {@link #set},
* {@code #get()} will call {@link #initialValue()} and create a new
* entry with the resulting value.
*
* @since 1.5
*/
public void remove() {
Thread currentThread = Thread.currentThread();
Values values = values(currentThread);
if (values != null) {
values.remove(this);
}
}
/**
* Creates Values instance for this thread and variable type.
*/
Values initializeValues(Thread current) {
return current.localValues = new Values();
}
/**
* Gets Values instance for this thread and variable type.
*/
Values values(Thread current) {
return current.localValues;
}
/** Weak reference to this thread local instance. */
private final Reference<ThreadLocal<T>> reference
= new WeakReference<ThreadLocal<T>>(this);
/** Hash counter. */
private static AtomicInteger hashCounter = new AtomicInteger(0);
/**
* Internal hash. We deliberately don't bother with #hashCode().
* Hashes must be even. This ensures that the result of
* (hash & (table.length - 1)) points to a key and not a value.
*
* We increment by Doug Lea's Magic Number(TM) (*2 since keys are in
* every other bucket) to help prevent clustering.
*/
private final int hash = hashCounter.getAndAdd(0x61c88647 * 2);
/**
* Per-thread map of ThreadLocal instances to values.
*/
代碼比較多,但是我們挑比較關(guān)鍵的地方看( set/get)
get:獲取當(dāng)前線程的localValues,如果是null的話,initializeValues一個(gè)localValues乐导。然后從localValues中獲取值苦丁。
set:獲取當(dāng)前線程的localValues,如果是null的話,initializeValues一個(gè)localValues。然后把值放入當(dāng)前線程中物臂。
- ThreadLocal本身并沒(méi)有存儲(chǔ)數(shù)據(jù)的能力旺拉,真正存儲(chǔ)數(shù)據(jù)的地方是存儲(chǔ)在當(dāng)前線程中。
- 每一個(gè)線程localValues是不同的棵磷。