Home >Java >javaTutorial >What is the implementation principle of ThreadLocal thread variables in Java

What is the implementation principle of ThreadLocal thread variables in Java

PHPz
PHPzforward
2023-05-16 21:07:10623browse

What is ThreadLocal?

ThreadLocal allows us to create thread-private variables. This variable is invisible to other threads. ThreadLocal creates a copy of the variable in each thread. Each thread can access its own private thread variables. The code example is as follows:

public class ThreadLocalDemo {
 
    //创建一个ThreadLocal对象,用来为每个线程会复制保存一份变量,实现线程封闭
    private  static ThreadLocal<Integer> localNum = new ThreadLocal<Integer>(){
        @Override
        protected Integer initialValue() {
            return 1;
        }
    };
 
    public static void main(String[] args) {
          //线程0
          new Thread(){
              @Override
              public void run() {
                   localNum.set(1);
                  try {
                      Thread.sleep(2000);
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
                  localNum.set(localNum.get()+10);
                  System.out.println(Thread.currentThread().getName()+":"+localNum.get());//11
              }
          }.start();
        //线程1
        new Thread(){
            @Override
            public void run() {
                localNum.set(3);
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                localNum.set(localNum.get()+20);
                System.out.println(Thread.currentThread().getName()+":"+localNum.get());//23
            }
        }.start();
        
        System.out.println(Thread.currentThread().getName()+":"+localNum.get());//0
    }
}

As mentioned above, counting the main thread and the two newly created threads, there are a total of three threads. Each thread contains its own private thread variables. Variable, here we set the value 1. The set() and get() methods are used to set and obtain the value. The execution results are as follows:

What is the implementation principle of ThreadLocal thread variables in Java

ThreadLocal implementation principle analysis

ThreadLocal is a generic class that can accept any type of object. It maintains a static internal class of ThreadLocalMap. The get(), set(), etc. we use actually come from this class, and will be The current thread creates a ThreadLocalMap object to record private values

What is the implementation principle of ThreadLocal thread variables in Java

First look at the set() method

public void set(T value) {
    //拿到当前线程
    Thread t = Thread.currentThread();
    //拿到当前线程map
    ThreadLocalMap map = getMap(t);
    if (map != null)
        //存在设置值
        map.set(this, value);
    else
        //不存在则创建
        createMap(t, value); 
}
void createMap(Thread t, T firstValue) {
    //threadLocals属性即为此map
    t.threadLocals = new ThreadLocalMap(this, firstValue);
}

Then the get() method

public T get() {
    //拿到当前线程
    Thread t = Thread.currentThread();
    //拿到当前线程对应的map
    ThreadLocalMap map = getMap(t);
    //如果已有map
    if (map != null) {
        //取值操作, 拿到对应的Entry
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null) {
           @SuppressWarnings("unchecked")
           T result = (T)e.value;
           return result;
        }
    }
    //没有map, 则去创建初始化一个map
    return setInitialValue();
}
private T setInitialValue() {
    //initialValue()方法返回的value为null
    T value = initialValue();
    //拿到当前线程去创建对应的map
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null)
        map.set(this, value);
    else
        createMap(t, value);
    return value;
}

ThreadLocal can be understood as an encapsulation of ThreadLocalMap

ThreadLocal memory leak problem

In ThreadLocalMap, the ThreadLocal object uses weak references as keys

What is the implementation principle of ThreadLocal thread variables in Java

In this case, if a ThreadLocal does not have an external strong reference, then the key is destined to be recycled by GC, which will cause the key in the ThreadLocalMap to be null, and the value still has a strong reference chain

A thread can With multiple ThreadLocals at the same time, if the key as a weak reference is recycled, the value cannot be recycled, then this will cause the life cycle of this ThreadLocal to be as long as this thread (because the strong reference chain of this value after the thread is executed will be interrupted), if the thread never ends and the accumulated value cannot be recycled, then a memory leak problem will occur.

The way to solve the problem here is: call ThreadLocal every time after using it The remove() method clears data

public void remove() {
    ThreadLocalMap m = getMap(Thread.currentThread());
    if (m != null)
       m.remove(this);
}

Here we look at the difference between key as a strong reference

If the key is used as a strong reference, then its life cycle is as long as the thread, and there is a stable Strong reference chains cannot be recycled, causing memory leaks. If they are used as weak references, the GC will automatically recycle them, and the value can be better recycled in the subsequent remove() method, so we generally use ThreadLocal Designed to be private static, use the remove() method to manually delete them after use

The above is the detailed content of What is the implementation principle of ThreadLocal thread variables in Java. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:yisu.com. If there is any infringement, please contact admin@php.cn delete