为什么要使用线程池
1.為什么要使用線程池
在java中,如果每個請求到達(dá)就創(chuàng)建一個新線程,開銷是相當(dāng)大的。在實(shí)際使用中,服務(wù)器在創(chuàng)建和銷毀線程上花費(fèi)的時間和消耗的系統(tǒng)資源都相當(dāng)大,甚至可能要比在處理實(shí)際的用戶請求的時間和資源要多的多。除了創(chuàng)建和銷毀線程的開銷之外,活動的線程也需要消耗系統(tǒng)資源。如果在一個jvm里創(chuàng)建太多的線程,可能會使系統(tǒng)由于過度消耗內(nèi)存或“切換過度”而導(dǎo)致系統(tǒng)資源不足。為了防止資源不足,服務(wù)器應(yīng)用程序需要采取一些辦法來限制任何給定時刻處理的請求數(shù)目,盡可能減少創(chuàng)建和銷毀線程的次數(shù),特別是一些資源耗費(fèi)比較大的線程的創(chuàng)建和銷毀,盡量利用已有對象來進(jìn)行服務(wù),這就是“池化資源”技術(shù)產(chǎn)生的原因。
線程池主要用來解決線程生命周期開銷問題和資源不足問題。通過對多個任務(wù)重復(fù)使用線程,線程創(chuàng)建的開銷就被分?jǐn)偟搅硕鄠€任務(wù)上了,而且由于在請求到達(dá)時線程已經(jīng)存在,所以消除了線程創(chuàng)建所帶來的延遲。這樣,就可以立即為請求服務(wù),使用應(yīng)用程序響應(yīng)更快。另外,通過適當(dāng)?shù)恼{(diào)整線程中的線程數(shù)目可以防止出現(xiàn)資源不足的情況。
2、常見線程池
①newSingleThreadExecutor
單個線程的線程池,即線程池中每次只有一個線程工作,單線程串行執(zhí)行任務(wù)
②newFixedThreadExecutor(n)
固定數(shù)量的線程池,沒提交一個任務(wù)就是一個線程,直到達(dá)到線程池的最大數(shù)量,然后后面進(jìn)入等待隊(duì)列直到前面的任務(wù)完成才繼續(xù)執(zhí)行
③newCacheThreadExecutor(推薦使用)
可緩存線程池, 當(dāng)線程池大小超過了處理任務(wù)所需的線程,那么就會回收部分空閑(一般是60秒無執(zhí)行)的線程,當(dāng)有任務(wù)來時,又智能的添加新線程來執(zhí)行。
④newScheduleThreadExecutor
大小無限制的線程池,支持定時和周期性的執(zhí)行線程
3、線程池常見參數(shù)
corePoolSize:線程池的大小。線程池創(chuàng)建之后不會立即去創(chuàng)建線程,而是等待線程的到來。當(dāng)當(dāng)前執(zhí)行的線程數(shù)大于改值是,線程會加入到緩沖隊(duì)列;
maximumPoolSize:線程池中創(chuàng)建的最大線程數(shù);
keepAliveTime:空閑的線程多久時間后被銷毀。默認(rèn)情況下,改值在線程數(shù)大于corePoolSize時,對超出corePoolSize值得這些線程起作用。
unit:TimeUnit枚舉類型的值,代表keepAliveTime時間單位,可以取下列值:
TimeUnit.DAYS; //天
TimeUnit.HOURS; //小時
TimeUnit.MINUTES; //分鐘
TimeUnit.SECONDS; //秒
TimeUnit.MILLISECONDS; //毫秒
TimeUnit.MICROSECONDS; //微妙
TimeUnit.NANOSECONDS; //納秒
workQueue:阻塞隊(duì)列,用來存儲等待執(zhí)行的任務(wù),決定了線程池的排隊(duì)策略,有以下取值:
ArrayBlockingQueue;
LinkedBlockingQueue;
SynchronousQueue;
threadFactory:線程工廠,是用來創(chuàng)建線程的。默認(rèn)new Executors.DefaultThreadFactory();
handler:線程拒絕策略。當(dāng)創(chuàng)建的線程超出maximumPoolSize,且緩沖隊(duì)列已滿時,新任務(wù)會拒絕,有以下取值:
ThreadPoolExecutor.AbortPolicy:丟棄任務(wù)并拋出RejectedExecutionException異常。
ThreadPoolExecutor.DiscardPolicy:也是丟棄任務(wù),但是不拋出異常。
ThreadPoolExecutor.DiscardOldestPolicy:丟棄隊(duì)列最前面的任務(wù),然后重新嘗試執(zhí)行任務(wù)(重復(fù)此過程)
ThreadPoolExecutor.CallerRunsPolicy:由調(diào)用線程處理該任務(wù)
總結(jié)
- 上一篇: Runnable和Thread的区别
- 下一篇: 线程池的处理流程和原理