涉及到類:Thread、ThreadLocal、ThreadLocalMap(ThreadLocal的內部類)
含義:這些變量與普通變量不同,每個訪問一個線程(通過其get或set方法)的線程都有其自己的,獨立初始化的變量副本。 ThreadLocal實例通常是希望將狀態與線程關聯的類中的私有靜態字段(例如,用戶ID或交易ID)
例子:
private static class ThreadA extends Thread {
@Override
public void run() {
// 每個訪問一個線程(通過其get或set方法)的線程都有其自己的,獨立初始化的變量副本
ThreadLocal<Integer> threadlocal = new ThreadLocal<Integer>();
threadlocal.set(1);
threadlocal.get();
}
}
源碼解析如下:(每一個Thread維護着一個ThreadLocalMap)
class Thread{
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
/*
* InheritableThreadLocal values pertaining to this thread. This map is
* maintained by the InheritableThreadLocal class.
*/
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null; // 用於繼承
}
當ThreadLocal的set方法
class ThreadLocal{
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
// 如果THreadLocalMap爲空,就新建一個
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
}
ThreadLocalMap getMap(Thread t) {
return t.threadLocals; // 獲得當前線程維護的ThreadLocalMap
}
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
ThreadLocalMap的key是對應的ThreadLocal<>
class ThreadLocal{
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
// 如果沒有ThreadLocalMap的初始值
return setInitialValue();
}
}
與線程生命狀態相關的體現
class Thread{
private void exit() {
if (group != null) {
group.threadTerminated(this);
group = null;
}
/* Aggressively null out all reference fields: see bug 4006245 */
target = null;
/* Speed the release of some of these resources */
threadLocals = null; // 退出時銷燬
inheritableThreadLocals = null;
inheritedAccessControlContext = null;
blocker = null;
uncaughtExceptionHandler = null;
}
}
ThreadLocal使用場景:
(1)使用實例:Handler、looper
class Looper{
// 獲得每個線程獨立的looper
private ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
// 新建looper其中維護着queue管理Messege,用於線程的通信
sThreadLocal.set(new Looper(quitAllowed));
}
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
}
(2)可用於靜態方法在多線程中的調用,獲得專屬當前的線程的內存區域(變量),這個是靜態變量無法實現,因爲靜態變量無法區分線程(Lopper實現方式一致)
public class Text {
private final static ThreadLocal<Integer> local = new ThreadLocal<Integer>(){
protected Integer initialValue() {
return 1;
}
};
public static int A() {
// 每一個線程都會有獨立的一份變量
Integer integer = local.get();
local.set(++integer);
return integer;
}
}