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

面試突擊:為什么創建線程池一定要用ThreadPoolExecutor?

開發 前端
線程池的創建方式總共分為兩大類:手動使用 ThreadPoolExecutor 創建線程池和自動使用 Executors 執行器創建線程池的方式。

在 Java 語言中,并發編程都是依靠線程池完成的,而線程池的創建方式又有很多,但從大的分類來說,線程池的創建總共分為兩大類:手動方式使用 ThreadPoolExecutor 創建線程池和使用 Executors 執行器自動創建線程池。那究竟要使用哪種方式來創建線程池呢?我們今天就來詳細的聊一聊。

先說結論

在 Java 語言中,一定要使用 ThreadPoolExecutor 手動的方式來創建線程池,因為這種方式可以通過參數來控制最大任務數和拒絕策略,讓線程池的執行更加透明和可控,并且可以規避資源耗盡的風險。

OOM風險演示

假如我們使用了 Executors 執行器自動創建線程池的方式來創建線程池,那么就會存現線程溢出的風險,以 CachedThreadPool 為例我們來演示一下:

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolExecutorExample {
static class OOMClass {
// 創建 1MB 大小的變量(1M = 1024KB = 1024*1024Byte)
private byte[] data_byte = new byte[1 * 1024 * 1024];
}
public static void main(String[] args) throws InterruptedException {
// 使用執行器自動創建線程池
ExecutorService threadPool = Executors.newCachedThreadPool();
List<Object> list = new ArrayList<>();
// 添加任務
for (int i = 0; i < 10; i++) {
int finalI = i;
threadPool.execute(new Runnable() {
@Override
public void run() {
// 定時添加
try {
Thread.sleep(finalI * 200);
} catch (InterruptedException e) {
e.printStackTrace();
}
//1M 對象添加到集合
OOMClass oomClass = new OOMClass();
list.add(oomClass);
System.out.println("執行任務:" + finalI);
}
});
}
}
}

第 2 步將 Idea 中 JVM 最大運行內存設置為 10M(設置此值主要是為了方便演示),如下圖所示:

以上程序的執行結果如下圖所示:

從上述結果可以看出,當線程執行了 7 次之后就開始出現 OutOfMemoryError 內存溢出的異常了。

內存溢出原因分析

想要了解內存溢出的原因,我們需要查看 CachedThreadPool 實現的細節,它的源碼如下圖所示:

構造函數的第 2 個參數被設置成了 Integer.MAX_VALUE,這個參數的含義是最大線程數,所以由于 CachedThreadPool 并不限制線程的數量,當任務數量特別多的時候,就會創建非常多的線程。而上面的 OOM 示例,每個線程至少要消耗 1M 大小的內存,加上 JDK 系統類的加載也要占用一部分的內存,所以當總的運行內存大于 10M 的時候,就出現內存溢出的問題了。

使用ThreadPoolExecutor來改進

接下來我們使用 ThreadPoolExecutor 來改進一下 OOM 的問題,我們使用 ThreadPoolExecutor 手動創建線程池的方式,創建一個最大線程數為 2,最多可存儲 2 個任務的線程池,并且設置線程池的拒絕策略為忽略新任務,這樣就能保證線程池的運行內存大小不會超過 10M 了,實現代碼如下:

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
* ThreadPoolExecutor 演示示例
*/
public class ThreadPoolExecutorExample {
static class OOMClass {
// 創建 1MB 大小的變量(1M = 1024KB = 1024*1024Byte)
private byte[] data_byte = new byte[1 * 1024 * 1024];
}

public static void main(String[] args) throws InterruptedException {
// 手動創建線程池,最大線程數 2,最多存儲 2 個任務,其他任務會被忽略
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, 2,
0L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(2),
new ThreadPoolExecutor.DiscardPolicy()); // 拒絕策略:忽略任務
List<Object> list = new ArrayList<>();
// 添加任務
for (int i = 0; i < 10; i++) {
int finalI = i;
threadPool.execute(new Runnable() {
@Override
public void run() {
// 定時添加
try {
Thread.sleep(finalI * 200);
} catch (InterruptedException e) {
e.printStackTrace();
}
//1m 對象添加到集合
OOMClass oomClass = new OOMClass();
list.add(oomClass);
System.out.println("執行任務:" + finalI);
}
});
}
// 關閉線程池
threadPool.shutdown();
// 檢測線程池的任務執行完
while (!threadPool.awaitTermination(3, TimeUnit.SECONDS)) {
System.out.println("線程池中還有任務在處理");
}
}
}

以上程序的執行結果如下圖所示:

從上述結果可以看出,線程池從開始執行到執行結束都沒有出現 OOM 的異常,這就是手動創建線程池的優勢。

其他創建線程池的問題

除了 CachedThreadPool 線程池之外,其他使用 Executors 自動創建線程池的方式,也存在著其他一些問題,比如 FixedThreadPool 它的實現源碼如下:

而默認情況下任務隊列 LinkedBlockingQueue 的存儲容量是 Integer.MAX_VALUE,也是趨向于無限大,如下圖所示:

這樣就也會造成,因為線程池的任務過多而導致的內存溢出問題。其他幾個使用 Executors 自動創建線程池的方式也存在此問題,這里就不一一演示了。

總結線程池的創建方式總共分為兩大類:手動使用 ThreadPoolExecutor 創建線程池和自動使用 Executors 執行器創建線程池的方式。其中使用 Executors 自動創建線程的方式,因為線程個數或者任務個數不可控,可能會導致內存溢出的風險,所以在創建線程池時,建議使用 ThreadPoolExecutor 的方式來創建。

責任編輯:武曉燕 來源: Java面試真題解析
相關推薦

2022-05-26 09:24:09

volatile懶漢模式

2019-01-29 11:02:30

消息中間件Java互聯網

2022-03-02 07:36:37

池化技術Java線程池

2018-08-24 09:02:26

2019-02-14 09:35:15

面試MQ中間件

2022-07-13 07:06:47

HTTPSHTTP協議

2021-03-05 11:02:14

iOS 14.5蘋果更新

2022-01-24 07:01:20

安全多線程版本

2020-12-23 13:29:15

微服務架構面試官

2019-09-19 15:12:27

Spring策略框架

2022-03-07 07:33:16

線程池Java語言

2021-12-13 09:10:48

equalshashCodeJava

2021-12-03 06:59:23

HashCodeEquals面試

2022-04-24 09:54:24

ProxyReflect前端

2011-05-10 15:51:34

SEO

2022-07-14 15:08:23

AI模型

2022-07-27 07:36:01

TCP可靠性

2022-01-10 13:06:13

微服務API網關

2022-02-18 12:24:39

PythonNumpy Arra大數據

2018-07-02 08:57:27

碼農業務程序員
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 天天影视综合 | 日韩成人免费视频 | 一区二区三区免费在线观看 | 精品一区二区免费视频 | 免费观看黄 | 一级黄色片美国 | 成人天堂噜噜噜 | 亚洲夜夜爽 | 久久久久国产一区二区三区不卡 | 色姑娘综合网 | 欧美在线亚洲 | 一级毛片免费完整视频 | 亚洲精品欧美 | av在线免费观看不卡 | 亚洲欧美日韩久久 | 欧美成年视频 | 国产一区二区在线播放 | 日韩中文字幕免费在线观看 | 91精品国产综合久久久久久丝袜 | 中文字幕av一区 | 国产精品久久久久久一区二区三区 | 91超碰在线观看 | 在线观看免费av网站 | 日日操天天射 | 成人免费在线视频 | 国产成人久久av免费高清密臂 | 国产精品夜夜夜一区二区三区尤 | 国产精品久久久久久吹潮 | 一区二区三区久久久 | 久久久免费在线观看 | 91大神xh98xh系列全部 | 欧美精品91| 国产精品久久久久久久久久 | 免费人成激情视频在线观看冫 | 日本aaaa | 国产99久久精品一区二区永久免费 | 成人av电影在线观看 | 久久久做 | 超碰成人免费观看 | 精品久| 国产精品久久久久久久久图文区 |