Android多线程之ThreadLocal

ThreadLocal简介

ThreadLocal实现的是线程的数据的本地存储,同一个ThreadLocal对象在不同的线程中都有自己的值,所有的线程共享同一个ThreadLocal对象,但是每一个访问它的线程都存储这个线程自己的值,并且一个线程改变了这个ThreadLocal对象的值但是并不能改变其他线程中ThreadLocal的值。ThreadLocal允许赋值为null。

ThreadLocal的主要方法

ThreadLocal的主要方法有set()方法,顾名思义,是对ThreadLocal进行赋值,get()方法则是取出当前线程中ThreadLocal的值,记住每一个线程中取出的值只是当前线程中之前所赋值。我们可以看一下ThreadLocal中的源码:

    public void set(T value) {
        Thread currentThread = Thread.currentThread();
        Values values = values(currentThread);
        if (values == null) {
            values = initializeValues(currentThread);
        }
        values.put(this, value);
    }

上述源码中我们可以看到set()方法所存储的值存放在了Values中,这个values是什么呢?我们可以接着看下一段源码:

 static class Values {
        private static final int INITIAL_SIZE = 16;
        private static final Object TOMBSTONE = new Object();
        private Object[] table;

        private int mask;

        private int size;

        private int tombstones;

        private int maximumLoad;

        private int clean;

        Values() {
            initializeTable(INITIAL_SIZE);
            this.size = 0;
            this.tombstones = 0;
        }

        Values(Values fromParent) {
            this.table = fromParent.table.clone();
            this.mask = fromParent.mask;
            this.size = fromParent.size;
            this.tombstones = fromParent.tombstones;
            this.maximumLoad = fromParent.maximumLoad;
            this.clean = fromParent.clean;
            inheritValues(fromParent);
        }

        @SuppressWarnings({"unchecked"})
        private void inheritValues(Values fromParent) {

            Object[] table = this.table;
            for (int i = table.length - 2; i >= 0; i -= 2) {
                Object k = table[i];

                if (k == null || k == TOMBSTONE) {

                    continue;
                }
tombstones and references.
                Reference> reference
                        = (Reference>) k;
            Object below.
                InheritableThreadLocal key = reference.get();
                if (key != null) {

                    table[i + 1] = key.childValue(fromParent.table[i + 1]);
                } else {
                    // The key was reclaimed.
                    table[i] = TOMBSTONE;
                    table[i + 1] = null;
                    fromParent.table[i] = TOMBSTONE;
                    fromParent.table[i + 1] = null;

                    tombstones++;
                    fromParent.tombstones++;

                    size--;
                    fromParent.size--;
                }
            }
        }

我们可以看到这个values是个静态内部类,其中的inheritValues方法我们可以看到我们存储的值实际上都是存放在了Object数组里。而get()方法我们可以看一下:

public T get() {
        // 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);
    }

源码中的描述很清晰,我们的值所在object数组中的索引实际就是index+1。还有remove()方法,这里remove()方法就不做详加解释,相信大家看名字亦能理解。

ThreadLocal的一个实现示例

这里写一个小的例子,帮助大家理解一下ThreadLocal:

  mFutureTest = new FutureTest();
        mFutureTest.test();
        mThreadLocal = new ThreadLocal();
        new Thread("thread_one"){
            @Override
            public void run() {
                mThreadLocal.set(1);
                Log.i("threadloacl","thread_one======"+mThreadLocal.get());
            }
        }.start();

        new Thread("thread_two"){
            @Override
            public void run() {
                mThreadLocal.set(2);
                Log.i("threadloacl","thread_two======"+mThreadLocal.get());
            }
        }.start();
        Log.i("threadlocal","mainthread="+mThreadLocal.get());

运行结果:

I/threadlocal: mainthread=null
I/threadloacl: thread_one======1
I/threadloacl: thread_two======2

这里在主线程中并没有赋值,所以主线程中的值为null。这就是关于ThreadLocal的我的浅显的理解,希望对看到这篇文章的人能有所增益,同时这也是方便我自己理解,加强记忆,如有纰漏之处还望指正!

你可能感兴趣的:(Android编程总结,android,多线程,线程,ThreadLoca)