Java創(chuàng)建線程池為什么一定要用ThreadPoolExecutor_第1頁
Java創(chuàng)建線程池為什么一定要用ThreadPoolExecutor_第2頁
Java創(chuàng)建線程池為什么一定要用ThreadPoolExecutor_第3頁
Java創(chuàng)建線程池為什么一定要用ThreadPoolExecutor_第4頁
Java創(chuàng)建線程池為什么一定要用ThreadPoolExecutor_第5頁
已閱讀5頁,還剩1頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

第Java創(chuàng)建線程池為什么一定要用ThreadPoolExecutor目錄先說結(jié)論OOM風(fēng)險演示內(nèi)存溢出原因分析使用ThreadPoolExecutor來改進其他創(chuàng)建線程池的問題總結(jié)前言:

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

先說結(jié)論

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

OOM風(fēng)險演示

假如我們使用了Executors執(zhí)行器自動創(chuàng)建線程池的方式來創(chuàng)建線程池,那么就會存現(xiàn)線程溢出的風(fēng)險,

以CachedThreadPool為例我們來演示一下:

importjava.util.ArrayList;

importjava.util.List;

importjava.util.concurrent.ExecutorService;

importjava.util.concurrent.Executors;

publicclassThreadPoolExecutorExample{

staticclassOOMClass{

//創(chuàng)建1MB大小的變量(1M=1024KB=1024*1024Byte)

privatebyte[]data_byte=newbyte[1*1024*1024];

publicstaticvoidmain(String[]args)throwsInterruptedException{

//使用執(zhí)行器自動創(chuàng)建線程池

ExecutorServicethreadPool=Executors.newCachedThreadPool();

ListObjectlist=newArrayList();

//添加任務(wù)

for(inti=0;ii++){

intfinalI=i;

threadPool.execute(newRunnable(){

@Override

publicvoidrun(){

//定時添加

try{

Thread.sleep(finalI*200);

}catch(InterruptedExceptione){

e.printStackTrace();

//將1M對象添加到集合

OOMClassoomClass=newOOMClass();

list.add(oomClass);

System.out.println("執(zhí)行任務(wù):"+finalI);

}

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

以上程序的執(zhí)行結(jié)果如下圖所示:

從上述結(jié)果可以看出,當線程執(zhí)行了7次之后就開始出現(xiàn)OutOfMemoryError內(nèi)存溢出的異常了。

內(nèi)存溢出原因分析

想要了解內(nèi)存溢出的原因,我們需要查看CachedThreadPool實現(xiàn)的細節(jié),它的源碼如下圖所示:

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

使用ThreadPoolExecutor來改進

接下來我們使用ThreadPoolExecutor來改進一下OOM的問題,我們使用ThreadPoolExecutor手動創(chuàng)建線程池的方式,創(chuàng)建一個最大線程數(shù)為2,最多可存儲2個任務(wù)的線程池,并且設(shè)置線程池的拒絕策略為忽略新任務(wù),這樣就能保證線程池的運行內(nèi)存大小不會超過10M了,

實現(xiàn)代碼如下:

importjava.util.ArrayList;

importjava.util.List;

importjava.util.concurrent.*;

*ThreadPoolExecutor演示示例

publicclassThreadPoolExecutorExample{

staticclassOOMClass{

//創(chuàng)建1MB大小的變量(1M=1024KB=1024*1024Byte)

privatebyte[]data_byte=newbyte[1*1024*1024];

publicstaticvoidmain(String[]args)throwsInterruptedException{

//手動創(chuàng)建線程池,最大線程數(shù)2,最多存儲2個任務(wù),其他任務(wù)會被忽略

ThreadPoolExecutorthreadPool=newThreadPoolExecutor(2,2,

0L,TimeUnit.SECONDS,newLinkedBlockingQueue(2),

newThreadPoolExecutor.DiscardPolicy());//拒絕策略:忽略任務(wù)

ListObjectlist=newArrayList();

//添加任務(wù)

for(inti=0;ii++){

intfinalI=i;

threadPool.execute(newRunnable(){

@Override

publicvoidrun(){

//定時添加

try{

Thread.sleep(finalI*200);

}catch(InterruptedExceptione){

e.printStackTrace();

//將1m對象添加到集合

OOMClassoomClass=newOOMClass();

list.add(oomClass);

System.out.println("執(zhí)行任務(wù):"+finalI);

//關(guān)閉線程池

threadPool.shutdown();

//檢測線程池的任務(wù)執(zhí)行完

while(!threadPool.awaitTermination(3,TimeUnit.SECONDS)){

System.out.println("線程池中還有任務(wù)在處理");

}

以上程序的執(zhí)行結(jié)果如下圖所示:

從上述結(jié)果可以看出,線程池從開始執(zhí)行到執(zhí)行結(jié)束都沒有出現(xiàn)OOM的異常,這就是手動創(chuàng)建線程池的優(yōu)勢。

其他創(chuàng)建線程池的問題

除了CachedThreadPool線程池之外,其他使用Executors自動創(chuàng)建線程池的方式,也存在著其他一些問題,

比如FixedThreadPool它的實現(xiàn)源碼如下:

而默認情況下任務(wù)隊列LinkedBlockingQueue的存儲容量是Integer.MAX_VALUE,也是趨向于無限大

如下圖所示:

這樣就也會造成,因為線程池的任務(wù)過多而導(dǎo)致的內(nèi)存溢出問題。其他幾個使用Executors自動創(chuàng)建線程池的方式也存在此問題,這里就不一一演示

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論