成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

阿里二面:ThreadLocal為什么會內存泄露

開發 前端
內存泄漏(Memory Leak)是指程序中已動態分配的堆內存由于某種原因程序未釋放或無法釋放,造成系統內存的浪費,導致程序運行速度減慢甚至系統崩潰等嚴重后果。

ThreadLocal基礎部分

ThreadLoal的作用

保存線程的獨立變量,這種變量在線程的生命周期內起作用,減少同一個線程內多個函數之間公共變量傳遞麻煩。

使用場景

需要給不同的線程保存不同的信息時。

基礎使用

public class TestThreadLocal {
private static ThreadLocal<Integer> threadLocal=new ThreadLocal<Integer>();
// private static ThreadLocal<Integer> threadLocal=new ThreadLocal<Integer>(){
//
// @Override
// protected Integer initialValue() {
// return 0;
// }
// };
public static void main(String[] args) {
Thread t1=new Thread(new Runnable() {
@Override
public void run() {
System.out.println(threadLocal.get());
}
});
Thread t2=new Thread(new Runnable() {
@Override
public void run() {
threadLocal.set(3);
System.out.println("t2:"+threadLocal.get());
}
});
t1.start();
t2.start();
System.out.println(threadLocal.get());
}
}

如果需要設置默認值的話,可以實現initialValue方法。

典型場景1:我們知道SimpleDateFormat的對象如果多線程使用的話會有線程不安全的問題。具體代碼如下:

public class TestThreadLocal {
public static ExecutorService executorService = Executors.newFixedThreadPool(16);
private static SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static void main(String[] args) throws InterruptedException {
for (int i=0;i<1000;i++){
executorService.submit(new Runnable() {
@Override
public void run(){
String format = simpleDateFormat.format(new Date());
try {
Date parse = simpleDateFormat.parse("2021-09-01 00:00:00");
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println(format);
}
});
}
Thread.sleep(3000);
executorService.shutdownNow();

}
}

運行結果如下:

可以看出,發生了異常。

方法1:我們可以改為每次都new一個新的SimpleDateFormat對象的話,這樣再運行是沒問題的。但是有些資源浪費。

方法2:使用ThreadLocal來解決。假設線程池里共16個線程,那我們總共16個SimpleDateFormat對象就可以應付所有的日期格式化的調用。

代碼如下:

public class TestThreadLocal {
public static ExecutorService executorService = Executors.newFixedThreadPool(16);
private static ThreadLocal<SimpleDateFormat> threadLocal=new ThreadLocal<SimpleDateFormat>(){
@Override
protected SimpleDateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
}
};
private static SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static void main(String[] args) throws InterruptedException {
for (int i=0;i<1000;i++){
executorService.submit(new Runnable() {
@Override
public void run() {
String format = threadLocal.get().format(new Date());
try {
Date parse = threadLocal.get().parse("2021-09-01 00:00:00");
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println(format);
}
});
}
Thread.sleep(3000);
executorService.shutdownNow();

}
}

注意: 如果不使用線程池,線程結束,線程里的threadLocalMap也會被回收。但是如果使用線程池,線程池里面的線程會被復用,線程里的threadLocalMap不會被回收,就造成了內存泄漏。按照正確的使用方法應該是每次用完了remove,但是這樣效率就很低。還不如方法1每次去new一個新的SimpleDateFormat對象。(但個人覺得其實還好,泄漏一點也沒關系,不過threadlocal畢竟不是專門解決線程安全問題的,不推薦這么用)

正確使用方法

  • 每次使用完ThreadLocal都調用它的remove()方法清除數據
  • 將ThreadLocal變量定義成private static,這樣就一直存在ThreadLocal的強引用,也就能保證任何時候都能通過ThreadLocal的弱引用訪問到Entry的value值,進而清除掉 。

ThreadLocal 高級部分

ThreadLocal為什么會內存泄露?

內存泄漏(Memory Leak)是指程序中已動態分配的堆內存由于某種原因程序未釋放或無法釋放,造成系統內存的浪費,導致程序運行速度減慢甚至系統崩潰等嚴重后果。

試想:

一個線程對應一塊工作內存,線程可以存儲多個ThreadLocal。那么假設,開啟1萬個線程,每個線程創建1萬個ThreadLocal,也就是每個線程維護1萬個ThreadLocal小內存空間,而且當線程執行結束以后,假設這些ThreadLocal里的Entry還不會被回收,那么將很容易導致堆內存溢出。

怎么辦?難道JVM就沒有提供什么解決方案嗎?

答案:

  1. JVM利用設置ThreadLocalMap的Key為弱引用,來避免內存泄露。
  2. JVM利用調用remove、get、set方法的時候,回收臟value值。

ThreadLocal的關系圖如下所示:

Thread里面維護了一個ThreadLocalMap,這個map里面的key是弱引用的readLocal實例。value是我們設置進去的值。當把treadLocal實例對象置為null后,沒有任何強引用指向threadLocal實例,所以theadLocal將會被gc回收。但是我們的value不會被回收,因為存在一個thread連接過來的強引用。只有當thread結束后,強引用斷開,map、value等將全部被回收。

如下圖:

但是很多時候我們使用線程池,為了復用線程,thread生命周期沒有結束,所以無法回收,造成內存泄漏。

責任編輯:姜華 來源: 今日頭條
相關推薦

2023-11-03 08:10:49

ThreadLoca內存泄露

2024-03-22 13:31:00

線程策略線程池

2025-04-01 05:22:00

JavaThread變量

2021-10-27 20:54:24

分庫分表高并發

2021-07-19 09:27:42

SSD內存Linux

2021-08-10 09:58:59

ThreadLocal內存泄漏

2022-08-26 07:33:49

內存JVMEntry

2022-09-05 16:55:23

RocketMQBroker

2021-04-25 09:58:48

mmapJava面試

2021-03-17 15:54:32

IO零拷貝方式

2024-10-31 09:24:42

2025-06-05 03:10:00

mmapmalloc共享內存

2022-05-09 14:09:23

多線程線程安全

2019-12-16 15:17:13

大數據信息安全數據庫

2024-09-29 08:57:25

2021-06-17 09:16:34

MySQL數據庫隔離級別

2024-05-28 08:09:27

2024-05-27 08:04:41

2021-04-23 20:59:02

ThreadLocal內存

2022-07-26 07:14:20

線程隔離Thread
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 毛片毛片毛片毛片毛片 | 亚洲欧美日韩一区二区 | 99成人| av中文字幕网站 | 欧美精品一区二区在线观看 | 久久久精品在线 | 欧美一区二区成人 | 精品在线观看一区二区 | 91在线精品一区二区 | 欧洲一级毛片 | 亚洲一二三区精品 | 精品国产一区二区三区久久 | 中文字幕人成乱码在线观看 | 久久人体视频 | 日日操操操 | 国产精品精品视频一区二区三区 | 美日韩一区二区 | 久久成人一区 | 天天干夜夜拍 | 国产免费人成xvideos视频 | 欧美va大片 | 欧美精品一区二区三区在线 | 日本中文字幕在线观看 | 欧美日韩国产高清 | 91麻豆精品国产91久久久久久久久 | 欧美成人高清视频 | 美女久久视频 | 亚洲精品v日韩精品 | 日朝毛片 | 天天操天天干天天爽 | 精品国产一二三区 | 一区二区三区国产 | 午夜精品一区 | 雨宫琴音一区二区在线 | 精品久久久一区 | 国产精品视频免费看 | 久久久国产一区二区三区 | 国产日韩精品视频 | 国产精品成av人在线视午夜片 | 久久青| 国产精品久久福利 |