Apakah sebab ThreadLocal menyebabkan memori OOM?
Lapisan asas ThreadLocal menyimpan data melalui ThreadLocalMap
Kod sumber adalah seperti berikut:
Apabila kami menggunakan ThreadLocal.set(), nilai dan kunci set (iaitu kelas ThreadLocal yang ditakrifkan oleh perniagaan) akan disimpan dalam tatasusunan Entry[] ThreadLocalMap
Kod sumber adalah seperti berikut:
Antaranya, Entry mengimplementasikan lemah rujukan WeakReference, dan kunci Entri (iaitu, kelas ThreadLocal yang ditakrifkan oleh pihak perniagaan) akan Ia dibalut menjadi rujukan yang lemah dan digunakan sebagai kunci Kemasukan. Takrifan rujukan lemah Java ialah apabila JVM melakukan imbasan kutipan sampah dan menemui objek dengan rujukan yang lemah sahaja, ia akan segera mengitar semula objek Ini adalah cara untuk menghalang limpahan memori apabila ThreadLocal pada asalnya direka
Kod sumber adalah seperti berikut:
Walaupun kuncinya dimasukkan ke dalam rujukan yang lemah dan akan dikitar semula oleh mekanisme pengumpulan sampah, nilai Mungkin ada rantai rujukan yang kuat apabila benang (Benang) tidak mati Memandangkan adalah rujukan yang kuat, selagi value
tidak mati, seperti. kumpulan benang, rantai rujukan yang kukuh ini akan wujud , kemudian Thread
tidak akan dikitar semula, yang boleh menyebabkan limpahan memori value
Hubungan rujukan adalah seperti berikut: Benang ==> ThreadLocalMap ==> Entri ==> nilai
Tetapi tindakan menghapuskan rantaian rujukan yang kuat ini perlu dicetuskan oleh pihak perniagaan dalam kes mendapatkan , atau mungkin kunci get tidak kosong, dan kelas expungeStaleEntry tidak akan dicetuskan. Oleh itu, pembangun harus membangunkan tabiat yang baik dan ingat untuk melaraskan kaedah sekali selepas menggunakan ThreadLocal
atau cara penggunaan yang betul ThreadLocal.remove()
ThreadLocal.set(null)
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; }
Cetak hasil:
14:30:26.790 [T2] INFO io.zhengsh.order.tool.ThreadLocalTest - Gunakan pembolehubah ThreadLocal :{"id":2,"level":" 2x ","name":"lanxing2"}14:30:26.789 [T5] INFO io.zhengsh.order.tool.ThreadLocalTest - Gunakan pembolehubah ThreadLocal :{"id":5,"level":"2x " ,"name":"lanxing5"}
14:30:26.792 [T0] INFO io.zhengsh.order.tool.ThreadLocalTest - Gunakan pembolehubah ThreadLocal :{"id":0,"level":"2x" , "name":"lanxing0"}
14:30:26.792 [T4] INFO io.zhengsh.order.tool.ThreadLocalTest - Gunakan pembolehubah ThreadLocal :{"id":4,"level":"2x", " name":"lanxing4"}
14:30:26.792 [T8] INFO io.zhengsh.order.tool.ThreadLocalTest - Gunakan pembolehubah ThreadLocal :{"id":8,"level":"2x"," name ":"lanxing8"}
14:30:26.791 [T1] INFO io.zhengsh.order.tool.ThreadLocalTest - Gunakan pembolehubah ThreadLocal :{"id":1,"level":"2x","name " :"lanxing1"}
14:30:26.792 [T7] INFO io.zhengsh.order.tool.ThreadLocalTest - Gunakan pembolehubah ThreadLocal :{"id":7,"level":"2x","name" : "lanxing7"}
14:30:26.792 [T6] INFO io.zhengsh.order.tool.ThreadLocalTest - Gunakan pembolehubah ThreadLocal :{"id":6,"level":"2x","name": " lanxing6"}
14:30:26.791 [T9] INFO io.zhengsh.order.tool.ThreadLocalTest - Gunakan pembolehubah ThreadLocal :{"id":9,"level":"2x","name":" lanxing9 "}
14:30:26.790 [T3] INFO io.zhengsh.order.tool.ThreadLocalTest - Gunakan pembolehubah ThreadLocal :{"id":3,"level":"2x","name":"lanxing3 " }
Atas ialah kandungan terperinci Apakah sebab mengapa ThreadLocal di Java menyebabkan limpahan memori (Out Of Memory)?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!