美文网首页
ThreadLocal源码分析

ThreadLocal源码分析

作者: ___刘辉良 | 来源:发表于2016-08-05 10:44 被阅读61次

最近查看Android,Looper源码的时候,看到一个这样的写法

static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

给我的第一印象是:
1.比较懒的一种单例的写法。
2.跟线程有很大的关系。不然怎么会叫做ThreadLocal呢?
3.觉得是一种集合,因为提供了get/set方法。 但是本身是单例,那么get出来不是同一个值吗?那不就是没有意义了吗?带着这些问题查看了一下源码。

public class ThreadLocal<T> {

    /* Thanks to Josh Bloch and Doug Lea for code reviews and impl advice. */

    /**
     * Creates a new thread-local variable.
     */
    public ThreadLocal() {}

    /**
     * Returns the value of this variable for the current thread. If an entry
     * doesn't yet exist for this variable on this thread, this method will
     * create an entry, populating the value with the result of
     * {@link #initialValue()}.
     *
     * @return the current value of the variable for the calling thread.
     */
    @SuppressWarnings("unchecked")
    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);
    }

    /**
     * Provides the initial value of this variable for the current thread.
     * The default implementation returns {@code null}.
     *
     * @return the initial value of the variable.
     */
    protected T initialValue() {
        return null;
    }

    /**
     * Sets the value of this variable for the current thread. If set to
     * {@code null}, the value will be set to null and the underlying entry will
     * still be present.
     *
     * @param value the new value of the variable for the caller thread.
     */
    public void set(T value) {
        Thread currentThread = Thread.currentThread();
        Values values = values(currentThread);
        if (values == null) {
            values = initializeValues(currentThread);
        }
        values.put(this, value);
    }

    /**
     * Removes the entry for this variable in the current thread. If this call
     * is followed by a {@link #get()} before a {@link #set},
     * {@code #get()} will call {@link #initialValue()} and create a new
     * entry with the resulting value.
     *
     * @since 1.5
     */
    public void remove() {
        Thread currentThread = Thread.currentThread();
        Values values = values(currentThread);
        if (values != null) {
            values.remove(this);
        }
    }

    /**
     * Creates Values instance for this thread and variable type.
     */
    Values initializeValues(Thread current) {
        return current.localValues = new Values();
    }

    /**
     * Gets Values instance for this thread and variable type.
     */
    Values values(Thread current) {
        return current.localValues;
    }

    /** Weak reference to this thread local instance. */
    private final Reference<ThreadLocal<T>> reference
            = new WeakReference<ThreadLocal<T>>(this);

    /** Hash counter. */
    private static AtomicInteger hashCounter = new AtomicInteger(0);

    /**
     * Internal hash. We deliberately don't bother with #hashCode().
     * Hashes must be even. This ensures that the result of
     * (hash & (table.length - 1)) points to a key and not a value.
     *
     * We increment by Doug Lea's Magic Number(TM) (*2 since keys are in
     * every other bucket) to help prevent clustering.
     */
    private final int hash = hashCounter.getAndAdd(0x61c88647 * 2);

    /**
     * Per-thread map of ThreadLocal instances to values.
     */

代码比较多,但是我们挑比较关键的地方看( set/get)
get:获取当前线程的localValues,如果是null的话,initializeValues一个localValues。然后从localValues中获取值。
set:获取当前线程的localValues,如果是null的话,initializeValues一个localValues。然后把值放入当前线程中。

  1. ThreadLocal本身并没有存储数据的能力,真正存储数据的地方是存储在当前线程中。
  2. 每一个线程localValues是不同的。

相关文章

网友评论

      本文标题:ThreadLocal源码分析

      本文链接:https://www.haomeiwen.com/subject/hvzcsttx.html