ThreadLocal <T> Analytical Code

We see the internal implementation activeJDBC framework ThreadLocal this class record for each unique connection thread

private static final ThreadLocal<HashMap<String, Connection>> connectionsTL = new ThreadLocal<>();

Feeling is knowledge, open source look. Look at the source code in the explanation

This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its get or set method) has its own, independently initialized copy of the variable. ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread (e.g., a user ID or Transaction ID).

This paper birds, blind translate what, is this:

This class provides a variable for exclusive thread. These variables are different from other ordinary variables, it is that each thread has its own independent variable is initialized (through get and set methods). Examples of this type commonly used in the field of private static class to implement each thread has its own state (eg userId, transaction ID, etc.).

Xianpao about the use of it,

package com.test.threadlocal;

public class TestController {
    
    private static int index = 0;
    private static String str = "这个字符串是每个线程共享的";
    // 这个变量,看似是一个类的静态属性,实则是每个线程有自己独有的区域
    private static ThreadLocal<String> threadStr = new ThreadLocal<String>() {
        @Override
        protected String initialValue() {
            return "main线程专享";
        }
    };      
    
    public static void main(String[] args) throws InterruptedException {
        for(int i = 0; i < 3; i++) {
            Thread t = new MyThread();
            t.start();
            t.join();
        }
        
        System.out.println(str);
        System.out.println(threadStr.get());
    }
    
    static class MyThread extends Thread{

        @Override
        public void run() {
            index++;
            str = "第" + index + "个str";
            threadStr.set("第" + index + "个threadStr");
        }
        
        
    }

}

In this example, the results can be seen from the print and threadStr str variable. str all threads read and write, threadStr within each thread has opened up a thread exclusive area. Next, we look at the implementation.
Look at the constructor

     /**
     * ThreadLocals rely on per-thread linear-probe hash maps attached
     * to each thread (Thread.threadLocals and
     * inheritableThreadLocals).  The ThreadLocal objects act as keys,
     * searched via threadLocalHashCode.  This is a custom hash code
     * (useful only within ThreadLocalMaps) that eliminates collisions
     * in the common case where consecutively constructed ThreadLocals
     * are used by the same threads, while remaining well-behaved in
     * less common cases.
     */
    private final int threadLocalHashCode = nextHashCode();
     /**
     * Creates a thread local variable.
     * @see #withInitial(java.util.function.Supplier)
     */
    public ThreadLocal() {
    }

The constructor is empty, however, the class has a private integer constant threadLocalHashCode . nextHashCode () method we do not read, as the source of the province like the deep sea. Wen bird watching, then, probably each new a ThreadLocal variable, it will generate a hash code, which after modulo some integer with a non-extreme circumstances is not easy to conflict (this sentence a bit lost it, in fact I do not know)
and then look at the set method

/**
     * Sets the current thread's copy of this thread-local variable
     * to the specified value.  Most subclasses will have no need to
     * override this method, relying solely on the {@link #initialValue}
     * method to set the values of thread-locals.
     *
     * @param value the value to be stored in the current thread's copy of
     *        this thread-local.
     */
    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

Easy to see that this method of setting each thread its own value, equivalent to the current thread is key, and then come to a ThreadLocalMap . Obviously, this map is used to save internal thread, of course, since it is map each thread can hold multiple values, and the value of the map we guess that I want to save a specific value, it is estimated that by the Object class declaration. What key is it? We look constructor ThreadLocalMap class.

/**
         * The table, resized as necessary.
         * table.length MUST always be a power of two.
         */
        private Entry[] table;
                
/**
         * Construct a new map initially containing (firstKey, firstValue).
         * ThreadLocalMaps are constructed lazily, so we only create
         * one when we have at least one entry to put in it.
         */
        ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
            table = new Entry[INITIAL_CAPACITY];
            int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
            table[i] = new Entry(firstKey, firstValue);
            size = 1;
            setThreshold(INITIAL_CAPACITY);
        }

Oh my God! This class does not inherit our imagination HashMap, or ConcurrentMap, but read the internal Map of realization of the students should be able to find HashMap implementation and realization of the Map is simply pale into insignificance, have not. It made the following steps in the constructor:

  1. Initializes an array size of 16 Entry
  2. Through the above said very fans HashCode hash value obtained modulo 15 index value to be stored in an array
  3. Construction Entry, and then save into
  4. Length is set to 1
  5. Set to limit the expansion of size 16 2/3

We do not see this is to use an array to achieve Map Well, we have seen the HashMap implementation, feel Sasa water friends.
Map of the set and get method is not analyzed. Get method of ThreadLocal we still have to stick out, after all, is what our main analysis

/**
     * Returns the value in the current thread's copy of this
     * thread-local variable.  If the variable has no value for the
     * current thread, it is first initialized to the value returned
     * by an invocation of the {@link #initialValue} method.
     *
     * @return the current thread's value of this thread-local
     */
    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();
    }

Visible, to get the current thread is used as a key to acquire Map, then get to the Entry entity with the current this. Finally, of course, get to the store of value.

I'm coding, I'm happy ~

This article from the blog article multiple platforms OpenWrite release!

Guess you like

Origin www.cnblogs.com/theone67/p/11884581.html