[ThreadLocal] Detailed explanation of Threadlocal

Table of contents

What is ThreadLocal

Implementation principle

Instructions

Simple example

memory leak problem


What is ThreadLocal

        ​​​​ ThreadLocal is a thread-level variable in Java, which provides a mechanism for thread-local variables. Each thread can independently access its own ThreadLocal variables without interfering with each other. The following explains the principle and usage of ThreadLocal in detail from beginning to end.

        ThreadLocal provides a thread isolation solution for data sharing problems in multi-threaded environments. EachThreadLocal object can store a thread-private copy of variables. Threads do not interfere with each other, achieving data isolation between different threads.

Implementation principle

        The core principle of ThreadLocal is to use a ThreadLocalMap type member variable in the Thread class to store data. ThreadLocalMap maintains an Entry array internally. Entry is a structure of key-value pairs. The key is the ThreadLocal object and the value is a copy of the variable of the corresponding thread.

        Each thread has an independent ThreadLocalMap object. Using the ThreadLocal object as a key, the corresponding value can be accessed in each thread. This achieves the isolation of data between different threads, and the threads do not affect each other.

Instructions

The following are common uses of ThreadLocal:

  • Create a ThreadLocal object: Create a ThreadLocal object by creating a subclass of ThreadLocal or using ThreadLocal's static factory method.
  • Set the variable value: Associate the variable value with the current thread through the set() method of ThreadLocal. Each thread can obtain its own copy of the variable through the get() method.
  • Get the variable value: Get a copy of the variable associated with the current thread through the get() method of ThreadLocal.
  • Remove variable value: Remove the copy of the variable associated with the current thread through ThreadLocal's remove() method.

Simple example

        When using ThreadLocal, a simple example is to record the ID of the user's request. The ID can be obtained during the entire request processing without passing it in each method parameter.

java
public class RequestIdHolder {
    private static ThreadLocal<String> requestIdHolder = new ThreadLocal<>();

    public static void setRequestId(String requestId) {
        requestIdHolder.set(requestId);
    }

    public static String getRequestId() {
        return requestIdHolder.get();
    }

    public static void clearRequestId() {
        requestIdHolder.remove();
    }
}

public class RequestHandler {
    public void handleRequest() {
        String requestId = generateRequestId();
        RequestIdHolder.setRequestId(requestId);

        // 处理请求逻辑
        // 可以在任何方法中通过RequestIdHolder.getRequestId()获取到请求ID

        // 处理结束后清除请求ID
        RequestIdHolder.clearRequestId();
    }

    private String generateRequestId() {
        // 生成请求ID的逻辑
        return "ABC123";
    }
}

        In the above example, RequestIdHolder is a tool class used to store the request ID, which uses ThreadLocal to achieve thread isolation. The setRequestId() method is used to set the request ID of the current thread, the getRequestId() method is used to obtain the request ID of the current thread, and the clearRequestId() method is used to Clear the request ID of the current thread.

        In the method of the RequestHandler class, first generate a request ID through the method, and pass The a> method to avoid memory leaks and data interference. . After the processing is completed, clear the request ID of the current thread through the method sets it to the current thread. Next, you can perform any request processing logic. In any method, you can obtain the request ID of the current thread through handleRequest()generateRequestId()RequestIdHolder.setRequestId()RequestIdHolder.getRequestId()RequestIdHolder.clearRequestId()

memory leak problem

        It should be noted that when using ThreadLocal, if the used ThreadLocal variables are not manually cleaned up in time, memory leaks will occur. This is because Entry in ThreadLocalMap holds a strong reference to ThreadLocal, and ThreadLocal does not have a weak reference to Entry. If ThreadLocal is not cleaned up, the Entry in ThreadLocalMap will always hold the ThreadLocal object, resulting in the ThreadLocal object not being garbage collected.

        In order to avoid memory leaks, you need to call the remove() method to clean up after using ThreadLocal to remove ThreadLocal from ThreadLocalMap. You can usually ensure proper cleanup of ThreadLocal by using a try-finally block, or use the new feature in Java 8, ThreadLocal.withInitial(), to create a ThreadLocal object, which will automatically clean up ThreadLocals that are no longer used.

Guess you like

Origin blog.csdn.net/miles067/article/details/132767102