ThreadLocal类

  ThreadLocal可以把一个对象保存在指定的线程中,对象保存后,只能在指定线程中获取保存的数据,对于其他线程来说则无法获取到数据。在安卓系统的Handler机制中,使用ThreadLocal来保证每一个Handler所在的线程都有一个独立的Looper对象。
  ThreadLocal是一个关于创建线程局部变量的类,其实就是这个变量的作用域是线程,其他线程访问不了。通常我们创建的变量是可以被任何一个线程访问的,而使用ThreadLocal创建的变量只能被当前线程访问,其他线程无法访问。

在Looper中的使用

  在这里使用ThreadLocal保存Looper,确保每个线程中只有一个Looper对象。

static final 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");
    }
    sThreadLocal.set(new Looper(quitAllowed));
}

原理

  ThreadLoacl.java中的public的方法只有三个:set()、get()、remove();

set()方法进行了以下操作:

1 . 获取当前线程;
2 . 使用当前线程获取一个ThreadLocalMap对象(ThreadLocalMap是threadLocal的内部类);
3 . 如果获取到的map对象不为空,则设置值,否则创建map然后设置值;

public void set(T var1) {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null)
        map.set(this, value);
    else
        createMap(t, value);
}

ThreadLocalMap getMap(Thread t) {
    return t.threadLocals;
}
    
void createMap(Thread t, T firstValue) {
    t.threadLocals = new ThreadLocalMap(this, firstValue);
}

  每个线程都有一个保存值的ThreadLocalMap对象,ThreadLocal的值就放在当前线程的ThreadLocalMap成员变量中,所以只能在本线程中访问,其他线程不能访问。

get()方法操作如下:

  首先取出当前线程的 ThreadLocalMap 对象,如果这个对象为空,则返回默认值;如果不为空,使用当前 ThreadLoacl 对象(this)获取 ThreadLocalMap 的 Entry 对象,返回 Entry 保存的 value 值。

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();
}

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;
}

void createMap(Thread t, T firstValue) {
    t.threadLocals = new ThreadLocalMap(this, firstValue);
}

remove()方法:

public void remove() {
    ThreadLocalMap m = getMap(Thread.currentThread());
    if (m != null)
        m.remove(this);
}

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
---------------------last line for now--------------------