看了網上一大堆寫ThreadLocal內存泄露的文章,全都是概念和源碼內容,沒有一篇模擬內存泄露的文章。所以決定自己寫一個跟大家一塊討論學習。
/**
* 模擬ThreadLocal內存泄露導致OOM
* JVM啓動參數 -Xms20M -Xmx20M -Xmn10M
* @param args
*/
public static void main(String[] args) {
// 是否調用remove方法
boolean doRemove = false;
// 加鎖,讓多個線程串行執行,避免多個線程同時佔用內存導致的內存溢出問題
Object lockObj = new Object();
// 開啓20個線程
ExecutorService executorService = Executors.newFixedThreadPool(20);
// 爲了不重複使用線程,用Map標記一下已經已使用過的線程,
Map<Long, Integer> threadIdMap = new ConcurrentHashMap<>();
// 循環向線程變量中設置數據 1024 * 1024 = 1M
for (int i = 0; i < 20; i++) {
executorService.execute(() -> {
synchronized (lockObj) {
Integer num = threadIdMap.putIfAbsent(Thread.currentThread().getId(), 1);
if (num == null) {
ThreadLocal<Byte[]> threadLocal = new ThreadLocal<>();
threadLocal.set(new Byte[1024 * 1024]);
if(doRemove) {
// 解決內存泄露關鍵
threadLocal.remove();
}
// 將threadLocal置爲空引用,利於回收
threadLocal = null;
// 手工回收
System.gc();
try {
// 調用GC後不一定會馬上回收
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName());
}
});
// System.out.println(i);
}
}