ThreadLocal details

Step 1: Analyze the source code of ThreadLocal

ThreadLocal has an inner class ThreadLocalMap, the implementation of this class accounts for more than half of the source code of the entire ThreadLocal class. The role of this ThreadLocalMap is very critical, it is the container where the thread really saves the thread's own local variables. Each thread has its own separate instance of ThreadLocalMap,

public T get() {
        //Get the current thread of execution
        Thread t = Thread.currentThread();
        //Get the ThreadLocalMap instance of the current thread
        ThreadLocalMap map = getMap(t);
        //If the map is not empty, it means that the thread already has a ThreadLocalMap instance
        if (map != null) {
            //map saves all thread local variables of the thread, we are going to find the current thread local variable
            ThreadLocalMap.Entry e = map.getEntry(this);
            //If the current thread local variable exists in this map, return its corresponding value
            if (e != null)
                return (T)e.value;
        }
        //If the map does not exist or the current thread local variable does not exist in the map, return the initial value
        return setInitialValue();
    }

Note that the last step here is to call

InitialValue() method to initialize local variables
The Thread object has an attribute threadLocals of type ThreadLocalMap, which is specially used to save all its own thread local variables. This property is null when the thread object is initialized. Therefore, when using a thread local variable for the first time for a thread object, you need to initialize the threadLocals property.
getMap method:

//Return directly to the threadLocals property of the thread object
ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }
setInitialValue method:

private T setInitialValue() {
        //Get the initialization value, initialValue is the method we covered before
        T value = initialValue();
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        //If the map is not empty, put the initialization value into the ThreadLocalMap object of the current thread
        if (map != null)
            map.set(this, value);
        else
            //The first time the current thread uses the local thread variable, the map needs to be initialized
            createMap(t, value);
        //return the initial value
        return value;
    }
Let's look at the set method again

public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);

        if (map != null)
            map.set(this, value);
        // Explain that the thread uses the thread local variable for the first time (note the first meaning here)
        else
            createMap(t, value);
    }
ThradLocal also has a remove method:
public void remove() {
         //Get the ThreadLocalMap object of the current thread
         ThreadLocalMap m = getMap(Thread.currentThread());
         //If the map is not empty, delete the value of the local variable
         if (m != null)
             m.remove(this);
     }

Step 2: Application Analysis

package com.threadlocal;

import java.util.logging.Logger;
	
public class threadlocaldemo {
	private static Logger logger =Logger.getLogger("threadlocaldemo.class");
	private static int id=0;
	private static ThreadLocal<People> threadLocal =new ThreadLocal<People>() {
		protected People initialValue() {
			
			People people =new People();
			 people.setId(++id);
			return people;
		};
	};
	public static void main(String[] args) {
		logger.info("Test started");
		for(int i=0;i<5;i++) {
			new Thread(new Runnable() {
				  public  void run() {
					  System.out.println("my name is :"+Thread.currentThread().getName()+"--"+threadLocal.get().getId());
				  };
			}).start();
		}
	}

}
result:
May 03, 2018 10:55:15 am com.threadlocal.threadlocaldemo main
INFO: Test started
my name is :Thread-3--3
my name is :Thread-5--2
my name is :Thread-4--1
my name is :Thread-2--1
my name is :Thread-1--1

From the results, it can be clearly seen that the effect of mutual isolation of variables between threads is not achieved.

private static int id=0;
	private static ThreadLocal<People> threadLocal =new ThreadLocal<People>() {
		protected People initialValue() {
			
			People people =new People();
			 people.setId(++id);
			return people;
		};
	};

model in this case

Case two:
package com.threadlocal;

import java.util.logging.Logger;
	
public class threadlocaldemo {
	private static Logger logger =Logger.getLogger("threadlocaldemo.class");

	private static ThreadLocal<People> threadLocal =new ThreadLocal<People>() {
		protected People initialValue() {
			int id=0;
			People people =new People();
			 people.setId(++id);
			return people;
		};
	};
	public static void main(String[] args) {
		logger.info("Test started");
		for(int i=0;i<5;i++) {
			new Thread(new Runnable() {
				  public  void run() {
					  System.out.println("my name is :"+Thread.currentThread().getName()+"--"+threadLocal.get().getId());
				  };
			}).start();
		}
	}

}

result:

INFO: Test started
my name is :Thread-5--1
my name is :Thread-1--1
my name is :Thread-3--1
my name is :Thread-4--1
my name is :Thread-2--1

Model:




Guess you like

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