java基础之ThreadLoacl
2019-07-27 本文已影响0人
暴走的小青春
相信很多人都会threadloacl有着自己的理解,android 里也到处有threadloacl的影子
比如:
public final class Looper {
private static final String TAG = "Looper";
// sThreadLocal.get() will return null unless you've called prepare().
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
private static Looper sMainLooper; // guarded by Looper.class
...
}
还有otto的bus中
public class Bus {
public static final String DEFAULT_IDENTIFIER = "default";
/** All registered event handlers, indexed by event type. */
private final ConcurrentMap<Class<?>, Set<EventHandler>> handlersByType =
new ConcurrentHashMap<Class<?>, Set<EventHandler>>();
/** All registered event producers, index by event type. */
private final ConcurrentMap<Class<?>, EventProducer> producersByType =
new ConcurrentHashMap<Class<?>, EventProducer>();
/** Identifier used to differentiate the event bus instance. */
private final String identifier;
/** Thread enforcer for register, unregister, and posting events. */
private final ThreadEnforcer enforcer;
/** Used to find handler methods in register and unregister. */
private final HandlerFinder handlerFinder;
/** Queues of events for the current thread to dispatch. */
private final ThreadLocal<ConcurrentLinkedQueue<EventWithHandler>> eventsToDispatch =
new ThreadLocal<ConcurrentLinkedQueue<EventWithHandler>>() {
@Override protected ConcurrentLinkedQueue<EventWithHandler> initialValue() {
return new ConcurrentLinkedQueue<EventWithHandler>();
}
};
都有其身影,有的还在定义时候重载了initialValue这个方法,那现在一探究竟,看看其原理所在
首先看其get方法
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;
}
}
return setInitialValue();
}
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
可以说先取出当前线程,然后把当前线程找到这个thread类的成员变量 ThreadLocalMap看其是否为null,如果不为空,就用此threadloacl对象作为key去找寻其value如果为空
private T setInitialValue() {
T value = initialValue();
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
return value;
}
就调用待复写的initialValue方法
在查看这个线程对应的ThreadLocalMap,如果有就set,没有就新建
举个例子:
a,b,c类在住线程定义了threadlocal对象,那么这个map的健就是三个threadlocal对象,值就是threadloacl里的值,因为他的map和当前的thread是紧密关联的
在set方法里就没啥好说的了
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
所以只要这个对象被放进不同的threadloacl里,比如是一个list:你在主线程add数据,那你在其他线程get是拿不到的,这也就是otto会把ConcurrentLinkedQueue<EventWithHandler>放进threadlocal的原理所在!