Multi-threaded Java Detailed -ThreadLocal

Brief introduction

ThreadLocal provide a JDK package, which provides a thread-local variables, that is, if you create a ThreadLocal variable, the variable access each thread will have a local copy of this variable. When multiple threads operating this variable, the actual operation of their own local memory inside the variable, thus avoiding thread-safety issues. After you create a ThreadLocal variable, each thread will copy a variable to its own local memory.

Simply put ThreadLocal is a kind of space for time approach, in which each Thread maintains a ThreadLocal.ThreadLocalMap, data isolation, do not share data for each thread, there is no natural problem of the security thread.

ThreadLocal can be achieved for each thread is bound own values, that is, each thread has a separate copy of each other is not affected. There are four methods: get, set, remove, initialValue. You can override initialValue () method to assign an initial value of ThreadLocal

example

This embodiment opens up two threads, each thread is provided in the interior of the value of the local variables, as follows:

public class ThreadLocalDemo {

    //创建ThreadLocal变量
    static ThreadLocal<String> localParam = new ThreadLocal<>();

    public static void main(String[] args) {
        //创建2个线程,分别设置不同的值
        new Thread(()->{
            localParam.set("hello java");
            //打印当前线程本地内存中的localParam变量的值
            System.out.println(Thread.currentThread().getName() + ":" + localParam.get());
        },"T1").start();
        new Thread(()->{
            localParam.set("hello web");
            System.out.println(Thread.currentThread().getName() + ":" + localParam.get());
        },"T2").start();
    }
}
复制代码

result:

T1:hello java
T2:hello web
复制代码

A description of each thread will have a local copy of this variable, when multiple threads operating this variable, the actual operation of their own local memory inside the variable.

The principle

ThreadLocal.ThreadLocalMap threadLocals = null;
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
复制代码

In fact, local variables for each thread is not stored in the ThreadLocal instance inside, but kept in the calling thread threadLocals variables inside . That is to say, ThreadLocal types of local variables in a specific thread memory space.

ThreadLocalMap Thread class has two types of variables, and are threadLocals inheritableThreadLocals, and a customized ThreadLocalMap Hashmap, designed to store the thread-local variables. By default, each thread in these two variables are null, only the current thread is not created until they call the ThreadLocal set or get methods for the first time.

ThreadLocal is a shell tool, which method the value set by the value placed threadLocals inside the calling thread and store it when calling thread calls its get method, and from threadLocals variable current thread inside it put to use .

If the calling thread has not terminated, then the local variable will always be stored in a variable threadLocals calling thread inside, so when the need to use local variables can delete the local variable from threadLocals inside the current thread by calling the remove method ThreadLocal variable.

Further Thread inside threadLocals structure is designed to map each thread may be associated with a plurality of ThreadLocal variable.

Detailed common method

set method

public void set(T value) {
    //获取当前线程
    Thread t = Thread.currentThread();
    //将当前线程作为key,去查找对应的线程变量,找到则设置
    ThreadLocalMap map = getMap(t);
    if (map != null)
        map.set(this, value);
    else
    //第一次调用就创建当前线程对应的ThreadLocalMap
        createMap(t, value);
}

ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
}

void createMap(Thread t, T firstValue) {
    t.threadLocals = new ThreadLocalMap(this, firstValue);
}
复制代码

If getMap (t) of the return value is not empty, the value is set to the value threadLocals put, that is the current value into the variable for the current thread in the memory variable threadLocals. threadLocals a HashMap configuration in which the key is the current instance ThreadLocal object reference, value is a value set by the transfer method.

If getMap (t) returns null then the method is the first call to set, then create threadLocals variable current thread.

get method

public T get() {
    //获取当前线程
    Thread t = Thread.currentThread();
    //获取当前线程的threadLocals变量
    ThreadLocalMap map = getMap(t);
    //如果threadLocals不为null,则返回对应本地变量的值
    if (map != null) {
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null) {
            @SuppressWarnings("unchecked")
            T result = (T)e.value;
            return result;
        }
    }
    //threadLocals为空则初始化当前线程的threadLocals成员变量
    return setInitialValue();
}

private T setInitialValue() {
    //初始化为Null
    T value = initialValue();
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null)
        map.set(this, value);
    else
        createMap(t, value);
    return value;
}

protected T initialValue() {
    return null;
}
复制代码

If there is no call set ThreadLocal method directly calling the get method will return null.

remove method

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

If the current thread threadLocals variable is not empty, then delete the specified local ThreadLocal instance variables in the current thread.

The role of ThreadLocal

Use ThreadLocal induction down to the class 2:

  • Save the thread context information can be obtained at any desired place.

Due to the nature of ThreadLocal, the same thread is set in a place, at any subsequent places you can get to. It can be used to save the thread context information.

How common such as a string of subsequent associate each request, may be performed with ThreadLocal set, need to log recording method in which subsequent to the acquisition request get arbitrarily id, string together such that the entire request.

For example, there are Spring's transaction management, with ThreadLocal storage Connection, so that each can get the same DAO Connection, transaction rollback can be submitted and other operations.

  • Thread-safe, avoid certain situations need to consider the performance loss caused by thread safety must be synchronized.

Limitations: Each thread to read and write data in ThreadLocal thread is isolated from each other will not affect, but update the shared object can not be solved ThreadLocal problem!

The ThreadLocal defined as static Another advantage is that, due to the strong references in ThreadLocal, then ThreadLocalMap in the corresponding Entry key will always exist, then remove the execution time can be correctly positioned and to delete!

最佳实践做法应该为:

try {
    // 其它业务逻辑
} finally {
    threadLocal对象.remove();
}
复制代码

Precautions

Note: In the case where the thread pool, when the treatment cycle is completed ThreadLocal traffic, best explicitly call remove () method, the value empty "thread-local variable" in the. Under normal circumstances the use of ThreadLocal will not cause a memory overflow, weak references only threadLocal, stored value remains strong references, if threadLocal is still a strong reference other objects, "thread-local" is not recycled.

to sum up

Value within each thread has a member variable called threadLocals, the type of the variable is HashMap, where the key to this ThreadLocal variables we define a reference, value was set we used a set method. Local variables for each thread is stored in its own memory variable threadLocals thread, if the current thread has not perish, these local variables will always exist, it may cause memory overflow, so remember to remove after use of the delete method call ThreadLocal local variables threadLocals the corresponding thread in.

Guess you like

Origin juejin.im/post/5e16e1d6f265da3e0b43324a