Java ThreadLocal class resolution

ThreadLocal类

It is used to provide a local variable for the thread, which is only used by a thread itself. This way of sacrificing space is exchanged for the efficiency of concurrency.

However, ThreadLocal is not designed to solve the problem of concurrency security. Each thread uses an independent copy. The performance of ThreadLocal instances in each thread may be different. Because of this feature, it can be used to design web In the application session, each user session connected to the web container will allocate a thread to it, and the session in each thread is different.

Verify that ThreadLocal is independent of the properties of each thread:

package test;

import java.util.HashMap;
import java.util.concurrent.*;

public class Test implements Callable<String>{
    private static final ThreadLocal<String> nameLocal = new ThreadLocal<>();
    private static final HashMap<String ,Integer> hashMap = new HashMap<>();

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Test t = new Test();
        ExecutorService executorService = Executors.newCachedThreadPool();
        Future<String> futureTask = executorService.submit(t);
        Future<String> futureTask1 = executorService.submit(t);
        System.out.println(futureTask.get());
        System.out.println(futureTask1.get());
    }

    @Override
    public String call() throws Exception {
        if(nameLocal.get() == null){
            int id = (int)(Math.random()*1000);
            nameLocal.set("id"+id);
        }
        if(hashMap.size() == 0){
            hashMap.put("key",(int)(Math.random()*1000));
        }
        Integer value = hashMap.get("key");
        return nameLocal.get()+"   "+value;
    }
}

result:

From the results, nameLocal is obviously created once in different threads, each thread is assigned an initialized empty nameLocal when it runs, and the hashMap also declared as static final is created once, and finally in two In the thread is the exact same hashMap. The above code is repeatedly run for many times, and the above phenomenon always occurs, and some accidental factors at runtime are also excluded.

From the source code:

ThreadLocal class set source code:

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

Thread class member variable threadLocals declaration:

	//Thread member variable threadLocals declaration
	    /* ThreadLocal values pertaining to this thread. This map is maintained
     * by the ThreadLocal class. */
    ThreadLocal.ThreadLocalMap threadLocals = null;

The set source code in ThreadLocal's inner class ThreadLocalMap:

	//ThreadLocalMap  set
	 /**
         * Set the value associated with key.
         *
         * @param key the thread local object
         * @param value the value to be set
         */
        private void set(ThreadLocal<?> key, Object value) {

            // We don't use a fast path as with get() because it is at
            // least as common to use set() to create new entries as
            // it is to replace existing ones, in which case, a fast
            // path would fail more often than not.

            Entry[] tab = table;
            int len = tab.length;
            int i = key.threadLocalHashCode & (len-1);

            for (Entry e = tab[i];
                 e != null;
                 e = tab[i = nextIndex(i, len)]) {
                ThreadLocal<?> k = e.get();

                if (k == key) {
                    e.value = value;
                    return;
                }

                if (k == null) {
                    replaceStaleEntry(key, value, i);
                    return;
                }
            }

            tab[i] = new Entry(key, value);
            int sz = ++size;
            if (!cleanSomeSlots(i, sz) && sz >= threshold)
                rehash();
        }

As can be seen from the source code above, the set method puts the variable into an instance of the class named ThreadLocalMap (in fact, this class is the inner class of ThreadLocal), and the instance of the inner class is taken from the member variable of the Thread class instance. arrived. It can be considered that one of the reasons why ThreadLocal can guarantee independence for each thread is that the ThreadLocalMap used to store data is independent of each thread.

Overview:

ThreadLocal is used to isolate data, which improves efficiency by preventing multiple threads from reading and writing the same data, and facilitates parameter passing in the same thread. But it is essentially different from the synchronized function


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325672315&siteId=291194637