国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

Java線程池的那些事

2019-11-15 01:13:43
字體:
來源:轉載
供稿:網友
java線程池的那些事

熟悉java多線程的朋友一定十分了解java的線程池,jdk中的核心實現類為java.util.concurrent.ThreadPoolExecutor。大家可能了解到它的原理,甚至看過它的源碼;但是就像我一樣,大家可能對它的作用存在誤解。現在問題來了,jdk為什么要提供java線程池?使用java線程池對于每次都創建一個新Thread有什么優勢?

對線程池的誤解

很長一段時間里我一直以為java線程池是為了提高多線程下創建線程的效率。創建好一些線程并緩存在線程池里,后面來了請求(Runnable)就從連接池中取出一個線程處理請求;這樣就避免了每次創建一個新Thread對象。直到前段時間我看到一篇Neal Gafter(和Joshua Bloch合著了《Java Puzzlers》,現任職于微軟,主要從事.NET語言方面的工作)的訪談,里面有這么一段談話(http://www.infoq.com/cn/articles/neal-gafter-on-java):

淺談java線程池

乍一看,大神的思路就是不一樣:java線程池是為了防止java線程占用太多資源?

雖然是java大神的訪談,但是也不能什么都信,你說占資源就占資源?還是得寫測試用例測一下。

首先驗證下我的理解:

java線程池和創建java線程哪個效率高?

直接上測試用例:

publicclassThreadPoolTestextendsTestCase{

這里使用Executors.newFixedThreadPool(100)是為了控制線程池的核心連接數和最大連接數一樣大,都為100。

我的機子上的測試結果:

testThreadPool:31testNewThread:624

可以看到,使用線程池處理10000個請求的處理時間為31ms,而每次啟用新線程的處理時間為624ms。

好了,使用線程池確實要比每次都創建新線程要快一些;但是testNewThread一共耗時624ms,算下平均每次請求的耗時為:

624ms/10000=62.4us

每次創建并啟動線程的時間為62.4微秒。根據80/20原理,這點兒時間根本可以忽略不計。所以線程池并不是為了效率設計的。

java線程池是為了節約資源?

再上測試用例:

publicclassThreadPoolTestextendsTestCase{publicvoidtestThread()throwsInterruptedException{inti=1;while(true){Runnablecommand=newTestRunnable();Threadthread=newThread(command);thread.start();System.out.println(i++);}}privatestaticclassTestRunnableimplementsRunnable{@Overridepublicvoidrun(){try{Thread.sleep(1000);}catch(InterruptedExceptione){e.printStackTrace();}}}}

以上用例模擬每次請求都創建一個新線程處理請求,然后默認每個請求的處理時間為1000ms。而在我的機子上當請求數達到1096時會內存溢出:

java.lang.OutOfMemoryError:unabletocreatenewnativethread

為什么會拋OOM Error呢?因為jvm會為每個線程分配一定內存(JDK5.0以后每個線程堆棧大小為1M,以前每個線程堆棧大小為256K,也可以通過jvm參數-Xss來設置),所以當線程數達到一定數量時就報了該error。

設想如果不使用java線程池,而為每個請求都創建一個新線程來處理該請求,當請求量達到一定數量時一定會內存溢出的;而我們使用java線程池的話,線程數量一定會<=maximumPoolSize(線程池的最大線程數),所以設置合理的話就不會造成內存溢出。

現在問題明朗了:java線程池是為了防止內存溢出,而不是為了加快效率。

淺談java線程池

上文介紹了java線程池啟動太多會造成OOM,使用java線程池也應該設置合理的線程數數量;否則應用可能十分不穩定。然而該如何設置這個數量呢?我們可以通過這個公式來計算:

(MaxProcessMemory – JVMMemory – ReservedOsMemory) / (ThreadStackSize) = Max number of threads

  • MaxProcessMemory 進程最大的內存
  • JVMMemoryJVM內存
  • ReservedOsMemoryJVM的本地內存
  • ThreadStackSize線程棧的大小
MaxProcessMemory

MaxProcessMemory:進程最大的尋址空間,當然也不能超過虛擬內存和物理內存的總和。關于不同系統的進程可尋址的最大空間,可參考下面表格:

Maximum Address Space Per Process
Operating SystemMaximum Address Space Per Process
Redhat linux 32 bit2 GB
Redhat Linux 64 bit3 GB
Windows 98/2000/NT/Me/XP2 GB
Solaris x86 (32 bit)4 GB
Solaris 32 bit4 GB
Solaris 64 bitTerabytes
JVMMemory

JVMMemory: Heap + PermGen,即堆內存和永久代內存和(注意,不包括本地內存)。

ReservedOsMemory

ReservedOSMemory:Native heap,即JNI調用方法所占用的內存。

ThreadStackSize

ThreadStackSize:線程棧的大小,JDK5.0以后每個線程堆棧大小默認為1M,以前每個線程堆棧大小為256K;可以通過jvm參數-Xss來設置;注意-Xss是jvm的非標準參數,不強制所有平臺的jvm都支持。

如何調大線程數?

如果程序需要大量的線程,現有的設置不能達到要求,那么可以通過修改MaxProcessMemory,JVMMemory,ThreadStackSize這三個因素,來增加能創建的線程數:

  碼農必須要加班?NO!

  知道碼農們都想擺脫加班狗、外賣臉的稱號,所以我們來了!

  我們做了一個能讓程序員之間共享知識技能的APP,覺得可以顛覆程序員的工作方 式!

  有人說我們癡心妄想,但我們不那么認為。

  為了能煽爛說我們癡心妄想的人的臉,現在我們急需程序員業內的牛嗶-人物來給 我們“號脈”!“診斷費”豐厚!畢竟我們不差錢兒,只是想做到最好!

  圈圈字典中講到,牛嗶-人物是指群成員數高于1000人的QQ群主或關注人數高于 2000人的貼吧吧主或粉絲人數高于10000人的微博博主或成員數高于2000主題貼的版主 或單帖閱讀量高于2000博客主或人脈超級廣的圈內紅人。

  對于未能達標的未來大神們,我們只能含淚表示:蜀黍,咱們來日方長,這次暫 時不約好嗎?待他日你立地成神,我必生死相依!

  來?還是不來?

  圈圈互動 接頭暗號:1955246408 (QQ)


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 清苑县| 金堂县| 荔浦县| 屏山县| 大洼县| 平乐县| 巩义市| 阳东县| 山阴县| 荣昌县| 五大连池市| 乐都县| 峡江县| 宁化县| 芦溪县| 丹阳市| 本溪市| 繁峙县| 伊金霍洛旗| 黄冈市| 芦溪县| 常熟市| 阜平县| 凤山县| 郯城县| 清徐县| 荥经县| 周宁县| 扎囊县| 深州市| 正安县| 台中县| 金秀| 磐安县| 保康县| 滕州市| 藁城市| 姚安县| 昭苏县| 波密县| 安远县|