java面試之線程池相關(guān)

  • 379.什么是線程池?

  • 什么是線程池贤徒?
    線程池是指在初始化一個多線程應用程序過程中創(chuàng)建一個線程集合芹壕,然后在需要執(zhí)行新的任務(wù)時重用這些線程而不是新建一個線程。線程池中線程的數(shù)量通常完全取決于可用內(nèi)存數(shù)量和應用程序的需求接奈。然而踢涌,增加可用線程數(shù)量是可能的。線程池中的每個線程都有被分配一個任務(wù)序宦,一旦任務(wù)已經(jīng)完成了睁壁,線程回到池子中并等待下一次分配任務(wù)。

  • 380.使用線程池有那些好處互捌?

    • 改進了一個應用程序的響應時間潘明。由于線程池中的線程已經(jīng)準備好且等待被分配任務(wù),應用程序可以直接拿來使用而不用新建一個線程秕噪。

為什么需要線程池钳降?
基于以下幾個原因在多線程應用程序中使用線程是必須的:

  1. 線程池改進了一個應用程序的響應時間。由于線程池中的線程已經(jīng)準備好且等待被分配任務(wù)腌巾,應用程序可以直接拿來使用而不用新建一個線程遂填。

  2. 線程池節(jié)省了CLR 為每個短生存周期任務(wù)創(chuàng)建一個完整的線程的開銷并可以在任務(wù)完成后回收資源。

  3. 線程池根據(jù)當前在系統(tǒng)中運行的進程來優(yōu)化線程時間片澈蝙。

  4. 線程池允許我們開啟多個任務(wù)而不用為每個線程設(shè)置屬性吓坚。

  5. 線程池允許我們?yōu)檎趫?zhí)行的任務(wù)的程序參數(shù)傳遞一個包含狀態(tài)信息的對象引用。

  6. 線程池可以用來解決處理一個特定請求最大線程數(shù)量限制問題灯荧。

線程池的概念
影響一個多線程應用程序的相應時間的幾個主要因素之一是為每個任務(wù)生成一個線程的時間礁击。

例如,一個Web Server 是一個多線程應用程序,它可以同時對多個客戶端請求提供服務(wù)客税。讓我們假設(shè)有十個客戶端同時訪問Web Server:

  1. 如果服務(wù)執(zhí)行一個客戶端對應一個線程的策略况褪,它將為這些客戶端生成十個新線程,從創(chuàng)建第一個線程開始到在線程的整個生命周期管理它們都會增加系統(tǒng)開銷更耻。也有可能在某個時間計算機的資源耗盡测垛。

  2. 相反的,如果服務(wù)端使用一個線程池來處理這些請求秧均,那么當每次客戶端請求來到后都創(chuàng)建一個線程的時間會節(jié)省下來食侮。它可以管理已經(jīng)創(chuàng)建的線程,如果線程池太忙的話也可以拒絕客戶端請求目胡。這是線程池背后的概念锯七。

.NET CLR 為服務(wù)請求維護一個線程池。如果我們的應用程序從線程池中請求一個新線程誉己,CLR 將試著從線程池中取出一個眉尸。如果線程池是空的,它將生成一個新線程并把它給我們巨双。當我們的代碼使用的線程結(jié)束以后噪猾,線程由.NET 回收并返回給線程池。線程池中線程的數(shù)量由當前可用地內(nèi)存數(shù)量決定筑累。

現(xiàn)在回顧一下袱蜡,影響設(shè)計一個多線程應用程序的因素有:

  1. 一個應用程序的響應時間。

  2. 線程管理資源的分配慢宗。

  3. 資源共享坪蚁。

  4. 線程同步。

第1種方式:配置Connector
maxThreads:tomcat可用于請求處理的最大線程數(shù)
minSpareThreads:tomcat初始線程數(shù)镜沽,即最小空閑線程數(shù)
maxSpareThreads:tomcat最大空閑線程數(shù)敏晤,超過的會被關(guān)閉
acceptCount:當所有可以使用的處理請求的線程數(shù)都被使用時,可以放到處理隊列中的請求數(shù)淘邻,超過這個數(shù)的請求將不予處理

<Connector port="8080" maxHttpHeaderSize="8192" maxThreads="150" minSpareThreads="25" maxSpareThreads="75" enableLookups="false" redirectPort="8443" acceptCount="100" connectionTimeout="20000" disableUploadTimeout="true" />  

第2種方式:配置Executor和Connector
name:線程池的名字
class:線程池的類名
namePrefix:線程池中線程的命名前綴
maxThreads:線程池的最大線程數(shù)
minSpareThreads:線程池的最小空閑線程數(shù)
maxIdleTime:超過最小空閑線程數(shù)時茵典,多的線程會等待這個時間長度,然后關(guān)閉
threadPriority:線程優(yōu)先級

<Executor name="tomcatThreadPool" namePrefix="req-exec-" maxThreads="1000" minSpareThreads="50" maxIdleTime="60000"/>  
  
<Connector port="8080" protocol="HTTP/1.1" executor="tomcatThreadPool"/>  

-如何創(chuàng)建線程池宾舅?
Java通過Executors提供四種線程池统阿,分別為:
newCachedThreadPool創(chuàng)建一個可緩存線程池,如果線程池長度超過處理需要筹我,可靈活回收空閑線程扶平,若無可回收,則新建線程蔬蕊。
newFixedThreadPool 創(chuàng)建一個定長線程池结澄,可控制線程最大并發(fā)數(shù),超出的線程會在隊列中等待。
newScheduledThreadPool 創(chuàng)建一個定長線程池麻献,支持定時及周期性任務(wù)執(zhí)行们妥。
newSingleThreadExecutor 創(chuàng)建一個單線程化的線程池,它只會用唯一的工作線程來執(zhí)行任務(wù)勉吻,保證所有任務(wù)按照指定順序(FIFO, LIFO, 優(yōu)先級)執(zhí)行监婶。

(1) newCachedThreadPool
創(chuàng)建一個可緩存線程池,如果線程池長度超過處理需要齿桃,可靈活回收空閑線程惑惶,若無可回收,則新建線程短纵。示例代碼如下:
Java代碼 收藏代碼
package test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExecutorTest {
public static void main(String[] args) {
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
final int index = i;
try {
Thread.sleep(index * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
cachedThreadPool.execute(new Runnable() {
public void run() {
System.out.println(index);
}
});
}
}
}

線程池為無限大带污,當執(zhí)行第二個任務(wù)時第一個任務(wù)已經(jīng)完成,會復用執(zhí)行第一個任務(wù)的線程香到,而不用每次新建線程鱼冀。

(2) newFixedThreadPool
創(chuàng)建一個定長線程池,可控制線程最大并發(fā)數(shù)悠就,超出的線程會在隊列中等待雷绢。示例代碼如下:
Java代碼 收藏代碼
package test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExecutorTest {
public static void main(String[] args) {
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
for (int i = 0; i < 10; i++) {
final int index = i;
fixedThreadPool.execute(new Runnable() {
public void run() {
try {
System.out.println(index);
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
}

因為線程池大小為3,每個任務(wù)輸出index后sleep 2秒理卑,所以每兩秒打印3個數(shù)字。
定長線程池的大小最好根據(jù)系統(tǒng)資源進行設(shè)置蔽氨。如Runtime.getRuntime().availableProcessors()

(3) newScheduledThreadPool
創(chuàng)建一個定長線程池藐唠,支持定時及周期性任務(wù)執(zhí)行。延遲執(zhí)行示例代碼如下:
Java代碼 收藏代碼
package test;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ThreadPoolExecutorTest {
public static void main(String[] args) {
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
scheduledThreadPool.schedule(new Runnable() {
public void run() {
System.out.println("delay 3 seconds");
}
}, 3, TimeUnit.SECONDS);
}
}

表示延遲3秒執(zhí)行鹉究。
定期執(zhí)行示例代碼如下:
Java代碼 收藏代碼
package test;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ThreadPoolExecutorTest {
public static void main(String[] args) {
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
public void run() {
System.out.println("delay 1 seconds, and excute every 3 seconds");
}
}, 1, 3, TimeUnit.SECONDS);
}
}

表示延遲1秒后每3秒執(zhí)行一次宇立。

(4) newSingleThreadExecutor
創(chuàng)建一個單線程化的線程池,它只會用唯一的工作線程來執(zhí)行任務(wù)自赔,保證所有任務(wù)按照指定順序(FIFO, LIFO, 優(yōu)先級)執(zhí)行妈嘹。示例代碼如下:
Java代碼 收藏代碼
package test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExecutorTest {
public static void main(String[] args) {
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
final int index = i;
singleThreadExecutor.execute(new Runnable() {
public void run() {
try {
System.out.println(index);
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
}

結(jié)果依次輸出,相當于順序執(zhí)行各個任務(wù)绍妨。
你可以使用JDK自帶的監(jiān)控工具來監(jiān)控我們創(chuàng)建的線程數(shù)量润脸,運行一個不終止的線程,創(chuàng)建指定量的線程他去,來觀察:
工具目錄:C:\Program Files\Java\jdk1.6.0_06\bin\jconsole.exe
運行程序做稍微修改:
Java代碼 收藏代碼
package test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExecutorTest {
public static void main(String[] args) {
ExecutorService singleThreadExecutor = Executors.newCachedThreadPool();
for (int i = 0; i < 100; i++) {
final int index = i;
singleThreadExecutor.execute(new Runnable() {
public void run() {
try {
while(true) {
System.out.println(index);
Thread.sleep(10 * 1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

效果如下:

選擇我們運行的程序:

監(jiān)控運行狀態(tài)

這里寫圖片描述
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末毙驯,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子灾测,更是在濱河造成了極大的恐慌爆价,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異铭段,居然都是意外死亡骤宣,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進店門序愚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來憔披,“玉大人,你說我怎么就攤上這事展运』钅妫” “怎么了?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵拗胜,是天一觀的道長蔗候。 經(jīng)常有香客問我,道長埂软,這世上最難降的妖魔是什么锈遥? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮勘畔,結(jié)果婚禮上所灸,老公的妹妹穿的比我還像新娘。我一直安慰自己炫七,他們只是感情好爬立,可當我...
    茶點故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著万哪,像睡著了一般侠驯。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上奕巍,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天吟策,我揣著相機與錄音,去河邊找鬼的止。 笑死檩坚,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的诅福。 我是一名探鬼主播匾委,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼权谁!你這毒婦竟也來了剩檀?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤旺芽,失蹤者是張志新(化名)和其女友劉穎沪猴,沒想到半個月后辐啄,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡运嗜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年壶辜,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片担租。...
    茶點故事閱讀 38,789評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡砸民,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出奋救,到底是詐尸還是另有隱情岭参,我是刑警寧澤,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布尝艘,位于F島的核電站演侯,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏背亥。R本人自食惡果不足惜秒际,卻給世界環(huán)境...
    茶點故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望狡汉。 院中可真熱鬧娄徊,春花似錦、人聲如沸盾戴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽尖啡。三九已至锐峭,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間可婶,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工援雇, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留矛渴,地道東北人。 一個月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓惫搏,卻偏偏與公主長得像具温,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子筐赔,可洞房花燭夜當晚...
    茶點故事閱讀 43,697評論 2 351

推薦閱讀更多精彩內(nèi)容