[java concurrent programming] ThreadLocal thread local class

 1. Introduction

The ThreadLocal class is provided as a local variable inside a thread. When these variables are accessed (get/set) in a multi-threaded environment, it can ensure that the variables in each thread are relatively independent of the variables in other threads.

Variables created through ThreadLocal can only be accessed by the current thread and are not visible to other threads, so other threads cannot access and modify them, that is to say: publicizing threads becomes private threading. In fact, each thread has a copy of the ThreadLocal variable.

Performance compared to locks:

The use of java in the use of locks will lead to a decrease in operating efficiency. The use of ThreadLocal completely avoids competition for shared resources without affecting efficiency. ThreadLocal adopts the method of "trading space for time", providing each thread with a copy of the variable, so as to achieve simultaneous access without affecting each other, but because each thread maintains a copy, the The memory usage will increase.

Two, ThreadLocal principle

ThreadLocalMap is a static inner class defined in the ThreadLocal class. And its structure is very similar to the HashMap structure. There is an Entry[] array to store data. And this Entry class is a subclass inherited from the WeakReference class, which is different from HashMap.

  

get method

The get() method is to take out the ThreadLocalMap from the Thread, and then use the ThreadLocal object as the Key to take out the value; the remove() method is to take out the ThreadLocalMap to remove the data corresponding to the ThreadLocal.

set method

When the set method is called, the data is written into the threadLocals Map object. The key of this Map is the current ThreadLocal object, and the value is the value we stored. And threadLocals itself can save multiple ThreadLocal objects, which is equivalent to a ThreadLocal collection.

The " open addressing method " is used to solve hash conflicts , which is different from the linked list method of hashmap

shortcoming

memory leak problem

The Key of Entry in ThreadLocalMap is a weak reference, so if you do not call the remove method to clear it after use, it will cause the corresponding value memory leak. So be sure to call the remove method to clear the data after use.

Three, ThreadLocal use

public class Main {
    //1、定义一个private static的ThreadLocal对象。
    private static ThreadLocal<String> threadLocal = new ThreadLocal<>();

    public static void main(String[] args) {
        //2、每个线程可以将当前线程需要存放在局部变量中,并且可以从中获取。
        threadLocal.set("");
        String s = threadLocal.get();

        //3、最后在使用完之后,需要将ThreadLocal中的值移除。
        threadLocal.remove();
    }
}

scenes to be used

It is mainly used for data isolation between threads.

For example: the tool class SimpleDateFormat is not thread-safe, you can place a copy in each thread through ThreadLocal to ensure thread safety.

Four, FastThreadLocal class

FastThreadLocal is a netty package, specifically the io.netty.util.concurrent package

1, derived from FastThreadLocal

Why is netty recreating a FastThreadLocal class ?

Because ThreadLocal is not efficient, specifically:

  • The variable bound to the current Thread is searched in the Map according to the ThreadLocal hash, which is not as fast as array subscript access.

  • When using the open addressing method to resolve hash conflicts, the efficiency is very low. That is to say, when the index of the hash is occupied, it will look back to see if there is a place to store it, and so on, until there is a space.

  • Map expansion involves recalculating part of the index, and in the worst case, moving the position of the element

  • When the thread is executed, it is best to clear the bound threadlocal variable, otherwise there will be a memory leak. In reality, it is often forgotten to clean up.

FastThreadLocal (hereinafter referred to as ftl) directly uses arrays to avoid hash conflicts.

The specific method is: when each FastThreadLocal instance is created, a subscript index is allocated; the allocation index is implemented using AtomicInteger, and each FastThreadLocal can obtain a unique subscript. When calling the ftl.get() method to get the value, get the return directly from the array, such as return array[index], as shown in the figure below:

Corresponding to the ThreadLocal class

There are three roles in the native ThreadLocal, Thread, ThreadLocal and ThreadLocalMap. Corresponding to Netty's FastThreadLocalThread, FastThreadLocal and InternalThreadLocalMap respectively.

2. How to use

<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-all</artifactId>
</dependency>

        //1、Netty提供的DefaultThreadFactory 工厂类,创建的线程默认就是 FastThreadLocalThread 类型
        DefaultThreadFactory defaultThreadFactory = new DefaultThreadFactory(FastThreadLocalTest.class);

        //2、创建FastThreadLocal
        FastThreadLocal<String> fastThreadLocal = new FastThreadLocal<>();

        //3、工厂生产线程
        Thread thread = defaultThreadFactory.newThread(() -> {
            //4、设置变量
            fastThreadLocal.set("");
            //5、获取变量
            fastThreadLocal.get();
        });
        //6、启动线程
        thread.start();

Guess you like

Origin blog.csdn.net/sumengnan/article/details/125070829