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

被開發者拋棄的 Executors,錯在哪兒?

開發 后端
本文我們聊了關于創建線程池,使用 Executors 創建的線程池會有 OOM 的風險,應該使用 ThreadPoolExecutor 去創建線程池。通過思考業務來明確配置線程池不同的參數,例如線程池、等待隊列、拒絕策略等等。

[[314663]]

 


一. 序

 

在 Java 領域內,我們使用多線程的方式來實現并發編程。而線程本身是操作系統的一個概念,雖然不同的語言對線程都進行了一些封裝,但是最終都是調用到操作系統中去創建和調度線程。

既然線程是一項重要的系統資源,為了更合理的利用此資源,我們會使用池化技術來優化線程的創建和銷毀,這就是線程池。

在我們學習并發編程的時候,線程可以利用 Thread 來創建并通過 start() 來啟動一個線,但在成熟的項目中,基本上是不允許這樣操作線程的,都需要通過線程池去收斂線程的使用,所以線程池是必須的。

Java 的線程池可以通過 ThreadPoolExecutor 來構造,在其中提供非常完備的構造方法,可以根據我們的業務需求靈活的構造線程池。同時 Java 還提供了一個 Executors,它內部提供了很多包裝的方法,利用它可以幫我們快速的構建線程池。

原本 Executors 的目的就是為了讓我們更方便的使用線程池,但是《阿里巴巴Java開發手冊》也明確指出,直接使用 Executors 的缺陷。

手冊中提到強制不允許使用 Executors 去創建線程池,而是應該使用退化到最原始的 ThreadPoolExecutor 的方式。

 

 

 

 

日常開發中,應該收緊對線程池的創建,由開發人員明確線程池的運行規則,以此來盡量規避其資源耗盡的風險。

線程池是個好東西,但是怎么創建是一個問題。

二. Executors 怎么了?

2.1 不被允許的 Executors

不應該使用 Executors 的原因,其實《阿里巴巴Java開發手冊》里已經寫明了,當需要處理大量任務的時候,可能會出現 OOM 異常,但它們出現 OOM 的原因并不一樣。

ThreadPoolExecutor 的構造方法中,提供了很多參數的配置,其中與 Executors 出現 OOM 相關的就有 2 個:核心線程數和等待隊列。

先來看看 FixedThreadPool 和 SingleThreadPool 出現 OOM 的原因。

它們的問題在于等待隊列使用了 LinkedBlockingQueue 這個以鏈表實現的無界隊列(最大長度是 Integer.MAX_VALUE),最終導致堆積了大量等待處理的任務,從而導致頻繁的 GC,最終觸發 OOM。

java.lang.OutOfMemoryError: GC overhead limit exceeded

再來看看 CachedThreadPool 出現 OOM 的原因。

它的問題在于核心線程數設置為了 Integer.MAX_VALUE,并且等待隊列是一個 SynchronousQueue。

SynchronousQueue 是一個沒有數據緩沖的阻塞隊列,它極易被阻塞。在等待隊列被阻塞的時候,如果線程數量還沒有達到核心線程數限制的數量時,線程池的策略是創建新的線程來處理新的任務。

也就是說,是核心線程數和等待隊列 SynchronousQueue 合力造成了線程會跟隨任務不斷的被創建,直到觸發 OOM。

java.lang.OutOfMemoryError: pthread_creat (1040KB stack) failed: Try again

ScheduledThreadPool 的等待隊列使用的是 DelayedWorkQueue,原理也是類似的,最終會導致創建大量的線程而拋出 OOM。

線程是一種系統資源,本身創建就會帶來內存開銷,同時操作系統對單進程可創建的線程數也是有限制的。

在 Android 中,每個線程初始化都需要 mmap 一定的堆內存,在默認的情況下,初始化一個線程大約需要 mmap 1MB 左右的內存空間。同時系統本身也會對每個進程可創建的線程數,做一定的限制,這個限制在 /proc/pid/limits 中,不同的廠商對這個限制也有所不同,當超出限制時,哪怕堆上還有可用內存,依然會拋出 OOM。

2.2 Executors 錯在哪兒了?

Executors 會在任務過多的時候,導致資源耗盡而觸發 OOM,這是它帶來的危害。

Executors 最大的問題,在于沒有邊界。

在系統環境良好,任務不多的時候 Executors 創建的線程池,都是可以正常工作的。

但是一旦有重壓,我們就無法預知什么時候會出現問題,這就是沒有邊界,沒有邊界就意味著不可控。

我們很難去信任一段不可控的代碼,它什么時候出現問題,完全是不可預知的,這才是 Executors 最大的問題。

除此之外,Executors 封裝了太多線程池的細節,本身也不建議使用。例如通常我們需要給線程池創建的線程,起一個有意義的名稱,方便在出現異常的時候排查問題;再例如對于線程池的拒絕策略,我們需要深思熟慮的定義,是直接拋棄還是持久化下來延遲處理。

去思考一個線程池的不同參數帶來的策略細節,才是使用線程池的一個良好的開發習慣。

三. 小結時刻

本文我們聊了關于創建線程池,使用 Executors 創建的線程池會有 OOM 的風險,應該使用 ThreadPoolExecutor 去創建線程池。通過思考業務來明確配置線程池不同的參數,例如線程池、等待隊列、拒絕策略等等。

今天就到這里,有任何問題,歡迎留言討論。

本文對你有幫助嗎?留言、轉發、點好看是最大的支持,謝謝!

責任編輯:武曉燕 來源: 承香墨影
相關推薦

2020-02-13 09:14:16

Executors開發Java

2014-04-29 14:52:06

大數據

2011-12-12 13:09:45

云計算

2015-08-27 13:45:25

2023-09-12 11:38:18

2019-07-23 16:00:36

區塊鏈存儲5G

2022-02-25 10:03:11

對象數據算法

2015-10-23 11:40:08

SaaS應用開發

2013-12-04 09:33:15

軟件成本

2014-04-17 10:16:50

2013-05-10 10:58:56

ERP

2017-06-22 10:39:06

Android開發者未來

2020-04-21 16:01:13

自動駕駛新基建工信部

2017-10-11 11:17:16

SaaS出路中國式

2024-11-21 17:35:10

2020-03-25 09:20:21

自然語言處理

2012-10-25 16:40:11

WOT高效數據中心數據中心

2015-01-08 14:52:29

google云計算分布式計算框架

2015-10-13 15:58:38

Javascript循環變量

2017-09-05 08:30:13

機箱智商產品
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: av中文在线播放 | 日韩视频在线播放 | 日韩欧美在线一区 | 日本免费在线看 | 日韩爱爱网站 | 国产91在线播放精品91 | 欧美一区二区三区在线观看 | 午夜爱爱网 | 久久九七 | 亚洲成人一区 | 国产精品日日做人人爱 | 国产精品欧美一区喷水 | 亚洲精品欧美精品 | 欧美激情国产日韩精品一区18 | 欧美视频免费在线 | www.成人.com| 久久国产精品久久 | 免费观看av网站 | 九色porny自拍视频 | 91亚洲精选 | 综合久久亚洲 | 国产精品免费看 | 欧美精品片 | 欧美日韩亚洲一区 | 久久一区视频 | 国产精品久久久99 | 国产高清在线精品一区二区三区 | 在线观看日本网站 | av在线黄 | 欧美一级在线 | 久在线视频 | 人人人人干 | 国产精品色婷婷久久58 | 国产成人精品999在线观看 | 国产精品久久久久久久久久尿 | 精品欧美黑人一区二区三区 | 亚洲三区视频 | 欧美影院 | 四虎成人免费视频 | 久久久国产精品一区 | 91视频在线观看免费 |