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的原理所在!

上一篇下一篇

猜你喜欢

热点阅读