ThreadLocal的理解

在看Handler源码的时候看到了 handler 构造函数中

 public Handler(Callback callback, boolean async) {
        if (FIND_POTENTIAL_LEAKS) {
            final Class klass = getClass();
            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                    (klass.getModifiers() & Modifier.STATIC) == 0) {
                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                    klass.getCanonicalName());
            }
        }

        mLooper = Looper.myLooper();   //这一句
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

  调用   mLooper = Looper.myLooper(); 

static final ThreadLocal sThreadLocal = new ThreadLocal();

 看  myLooper()方法  

 public static Looper myLooper() {
        return sThreadLocal.get();
    }
发现sThreadLocal是一个Threadlocal类  于是不解是如何通过这个对象获取到looper对象的   查看ThreadLocal的源码  

 public void set(T value) {  
        Thread currentThread = Thread.currentThread();   //获取当前线程  
        Values values = values(currentThread);    //获取当前线程中的values
        if (values == null) {      //如果没有 那么 new一个   
            values = initializeValues(currentThread);
        }
        values.put(this, value);   //得到values之后 将 当前 ThreadLocal和Thread关联  经过一些映射  找到一个合适的位置存放 ThreadLocal 
					//下一个位置存放存放的内容
    }

@SuppressWarnings("unchecked")
    public T get() {  //获取的时候  先获取当前线程  得到当前线程的 values  如果得到了 那么得到values中的table  经过映射获取要得到的位置  然后取下一个位置
				//就是要得到的值。 如果没找到  那么就创建一个返回。。
        // 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);
    }
其中  源码 注解中解释说  这个方法将返回一个和当前线程相关的Entry  如果不存在  将创建一个  也就是说  这个方法可以返回一个  与当前线程相关的Looper 对象   
然后源码中有些地方没看太懂  我大致理解的意思  应该是  通过values 方法传入当前线程  寻找当前与当前线程相关的Values对象  如果这个对象不为空  说明找到  通过hash映射 找到这个线程相关的对象的位置,然后对比reference (这个对象是一个Threadlocal的弱引用)(此处不解。。)  然后如果对比成功  返回   如果不成功 创建一个。。。
然后在网上查找资料,发现网上资料的源码 与我的源码不同   是使用一个叫  ThreadLocalMap的静态内部类   而我的代码中是Values这个内部类   可能这两个类的功能类似吧。。 
然后 “它实现了键值对的设置和获取(对比Map对象来理解),每个线程中都有一个独立的ThreadLocalMap副本,它所存储的值,只能被当前线程读取和修改。ThreadLocal类通过操作每一个线程特有的ThreadLocalMap副本,从而实现了变量访问在不同线程中的隔离。因为每个线程的变量都是自己特有的,完全不会有并发错误。还有一点就是,ThreadLocalMap存储的键值对中的键是this对象指向的ThreadLocal对象,而值就是你所设置的对象了。” 这是在网上找到的资料     也就是说Values可能是每个线程都独有的一个副本,它存的值  只能被当前线程访问 而ThreadLocal通过传入的线程操作这个线程特有的副本来防止多线程引发的并发问题  因为已经不存在同时访问同一个资源这个问题了   所以可以取得与线程相关的looper对象 
理解的可能有错误   但是大体思路应该是对的吧   以后认识加深了再来修改。。

其中在Looper中  存在一个

 static final ThreadLocal sThreadLocal = new ThreadLocal();  对象  

这个对象在prepare()的时会根据当前线程放入一个looper对象   所以Looper中的sThreadLocal中 会存放很多looper对象  根据线程对象来获取线程相关的looper即可




你可能感兴趣的:(android)