What is the reason why ThreadLocal causes memory OOM?
The underlying layer of ThreadLocal stores data through ThreadLocalMap
The source code is as follows:
When we use ThreadLocal.set(), the value and key of the set (that is, the ThreadLocal class defined by the business itself) will be stored in the Entry[] array of ThreadLocalMap
The source code is as follows:
Entry implements a weak reference WeakReference, and the key of Entry (that is, the ThreadLocal class defined by the business party) will It is wrapped into a weak reference and used as the Entry key. The definition of Java's weak reference is that when the JVM performs a garbage collection scan and finds an object with only weak references, it will immediately recycle the object. This is a means of preventing memory overflow when ThreadLocal was originally designed.
The source code is as follows:
Although the key is packaged into a weak reference and will be recycled by the garbage collection mechanism, the value There may be a strong reference chain when the thread (Thread) does not die.
Since value
is a strong reference, as long as Thread
does not die, such as the thread pool, This strong reference chain will exist, then value
will not be recycled, which may cause memory overflow.
The reference relationship is as follows: Thread ==> ThreadLocalMap == > Entry ==> value
But this action of eliminating the strong reference chain needs to be triggered by the business party in the case of get. Maybe the business party does not know how to get, or maybe the key of get is not empty. , and the expungeStaleEntry class will not be triggered. Therefore, developers should develop good habits and remember to call the ThreadLocal.remove()
method or ThreadLocal.set(null)
# when they are finished. ##Correct usage
public class ThreadLocalTest { /** * 未初始化的本地线程变量 */ private static ThreadLocal<User> userThreadLocal = new ThreadLocal<>(); public static void main(String[] args) throws InterruptedException { int threadNum = 10; List<Thread> threadList = Lists.newArrayList(); for (int i = 0; i < threadNum; ++i) { long userId = i; Thread t = new Thread(() -> { try { // 设置变量值 userThreadLocal.set(new User(userId, "lanxing" + userId, "2x")); // 使用变量 doSomething(); } finally { // 移除变量 userThreadLocal.remove(); //移除ThreadLocal变量 } }, "T" + i); threadList.add(t); t.start(); } for (int i = 0; i < threadNum; ++i) { threadList.get(i).join(); } } private static void doSomething() { log.info("Use ThreadLocal variable :{}", JSON.toJSONString(userThreadLocal.get())); } } @Data @NoArgsConstructor @AllArgsConstructor class User { private Long id; private String name; private String level; }
14:30:26.790 [T2] INFO io.zhengsh.order.tool .ThreadLocalTest - Use ThreadLocal variable :{"id":2,"level":"2x","name":"lanxing2"}
14:30:26.789 [T5] INFO io.zhengsh.order.tool. ThreadLocalTest - Use ThreadLocal variable :{"id":5,"level":"2x","name":"lanxing5"}14:30:26.792 [T0] INFO io.zhengsh.order.tool.ThreadLocalTest - Use ThreadLocal variable :{"id":0,"level":"2x","name":"lanxing0"}14:30:26.792 [T4] INFO io.zhengsh.order.tool.ThreadLocalTest - Use ThreadLocal variable :{"id":4,"level":"2x","name":"lanxing4"}
14:30:26.792 [T8] INFO io.zhengsh.order.tool.ThreadLocalTest - Use ThreadLocal variable :{"id":8,"level":"2x","name":"lanxing8"}
14:30:26.791 [T1] INFO io.zhengsh.order.tool.ThreadLocalTest - Use ThreadLocal variable :{"id":1,"level":"2x","name":"lanxing1"}
14:30:26.792 [T7] INFO io.zhengsh.order.tool.ThreadLocalTest - Use ThreadLocal variable :{"id":7,"level":"2x","name":"lanxing7"}
14:30:26.792 [T6] INFO io.zhengsh.order.tool.ThreadLocalTest - Use ThreadLocal variable : {"id":6,"level":"2x","name":"lanxing6"}
14:30:26.791 [T9] INFO io.zhengsh.order.tool.ThreadLocalTest - Use ThreadLocal variable :{ "id":9,"level":"2x","name":"lanxing9"}
14:30:26.790 [T3] INFO io.zhengsh.order.tool.ThreadLocalTest - Use ThreadLocal variable :{" id":3,"level":"2x","name":"lanxing3"}
The above is the detailed content of What is the reason why ThreadLocal in Java causes memory overflow (Out Of Memory)?. For more information, please follow other related articles on the PHP Chinese website!