線(xiàn)程是一個(gè)重量級(jí)的對(duì)象,應(yīng)該避免頻繁創(chuàng)建和銷(xiāo)毀矢否。原因:創(chuàng)建線(xiàn)程需要調(diào)用操作系統(tǒng)API仲闽,然后os為線(xiàn)程分配資源
線(xiàn)程池使用的生產(chǎn)者-消費(fèi)者模式:線(xiàn)程池的使用者是生產(chǎn)者,線(xiàn)程池本身就是消費(fèi)者僵朗,工作隊(duì)列就是那么擁塞隊(duì)列赖欣。線(xiàn)程池會(huì)根據(jù)初始化的大小申請(qǐng)這些數(shù)量的線(xiàn)程,此時(shí)線(xiàn)程里并沒(méi)有任務(wù)验庙,同時(shí)線(xiàn)程池有一個(gè)工作隊(duì)列顶吮,在初始化階段也可被初始化。execute()方法提交一個(gè)工作方法粪薛,也就是給線(xiàn)程池里的線(xiàn)程提交一個(gè)干活的模板悴了,這些線(xiàn)程都根據(jù)這個(gè)模板分別處理工作隊(duì)列中的任務(wù)。當(dāng)然,處理的過(guò)程中可能會(huì)有其他新的任務(wù)進(jìn)來(lái)湃交,放入到工作隊(duì)列中等待熟空。
使用 Java 中的線(xiàn)程池
Java 提供的線(xiàn)程池相關(guān)的工具類(lèi)中,最核心的是 ThreadPoolExecutor
把線(xiàn)程池類(lèi)比為一個(gè)項(xiàng)目組巡揍,而線(xiàn)程就是項(xiàng)目組的成員。
corePoolSize:表示線(xiàn)程池保有的最小線(xiàn)程數(shù)菌瘪。有些項(xiàng)目很閑腮敌,但是也不能把人都撤了,至少要留 corePoolSize 個(gè)人堅(jiān)守陣地俏扩。
maximumPoolSize:表示線(xiàn)程池創(chuàng)建的最大線(xiàn)程數(shù)糜工。當(dāng)項(xiàng)目很忙時(shí),就需要加人录淡,但是也不能無(wú)限制地加捌木,最多就加到 maximumPoolSize 個(gè)人。當(dāng)項(xiàng)目閑下來(lái)時(shí)嫉戚,就要撤人了刨裆,最多能撤到 corePoolSize 個(gè)人。
keepAliveTime & unit:上面提到項(xiàng)目根據(jù)忙閑來(lái)增減人員彬檀,那在編程世界里帆啃,如何定義忙和閑呢?很簡(jiǎn)單窍帝,一個(gè)線(xiàn)程如果在一段時(shí)間內(nèi)努潘,都沒(méi)有執(zhí)行任務(wù),說(shuō)明很閑坤学,keepAliveTime 和 unit 就是用來(lái)定義這個(gè)“一段時(shí)間”的參數(shù)疯坤。也就是說(shuō)深浮,如果一個(gè)線(xiàn)程空閑了keepAliveTime & unit這么久压怠,而且線(xiàn)程池的線(xiàn)程數(shù)大于 corePoolSize ,那么這個(gè)空閑的線(xiàn)程就要被回收了飞苇。
workQueue:工作隊(duì)列刑峡,和上面示例代碼的工作隊(duì)列同義。
threadFactory:通過(guò)這個(gè)參數(shù)你可以自定義如何創(chuàng)建線(xiàn)程玄柠,例如你可以給線(xiàn)程指定一個(gè)有意義的名字突梦。
handler:通過(guò)這個(gè)參數(shù)你可以自定義任務(wù)的拒絕策略。如果線(xiàn)程池中所有的線(xiàn)程都在忙碌羽利,并且工作隊(duì)列也滿(mǎn)了(前提是工作隊(duì)列是有界隊(duì)列)宫患,那么此時(shí)提交任務(wù),線(xiàn)程池就會(huì)拒絕接收这弧。至于拒絕的策略娃闲,你可以通過(guò) handler 這個(gè)參數(shù)來(lái)指定虚汛。
????????1 .CallerRunsPolicy:提交任務(wù)的線(xiàn)程自己去執(zhí)行該任務(wù)。??
????????2. AbortPolicy:默認(rèn)的拒絕策略皇帮,會(huì) throws RejectedExecutionException卷哩。
????????3.DiscardPolicy:直接丟棄任務(wù),沒(méi)有任何異常拋出属拾。
????????4.DiscardOldestPolicy:丟棄最老的任務(wù)将谊,其實(shí)就是把最早進(jìn)入工作隊(duì)列的任務(wù)丟棄,然后把新任務(wù)加入到工作隊(duì)列渐白。
Executors靜態(tài)工廠類(lèi)提供了快速創(chuàng)建線(xiàn)程池的方法
1. ExecutorServiceexecutorService = Executors.newSingleThreadExecutor();??創(chuàng)建一個(gè)單線(xiàn)程化的Executor
2.ExecutorServiceexecutorService = Executors.newCachedThreadPool();??創(chuàng)建一個(gè)可緩存的線(xiàn)程池尊浓,調(diào)用execute 將重用以前構(gòu)造的線(xiàn)程(如果線(xiàn)程可用)。如果沒(méi)有可用的線(xiàn)程纯衍,則創(chuàng)建一個(gè)新線(xiàn)程并添加到池中栋齿。終止并從緩存中移除那些已有 60 秒鐘未被使用的線(xiàn)程。
3.ExecutorServiceexecutorService = Executors.newFixedThreadPool(大小);?創(chuàng)建固定數(shù)目線(xiàn)程的線(xiàn)程池
4.ExecutorServiceexecutorService = Executors.newScheduledThreadPool(大小);??創(chuàng)建一個(gè)支持定時(shí)及周期性的任務(wù)執(zhí)行的線(xiàn)程池襟诸,多數(shù)情況下可用來(lái)替代Timer類(lèi)瓦堵。
Executors提供的許多方法使用的無(wú)界的工作隊(duì)列,高負(fù)載情況下可能會(huì)OOM歌亲,不安全谷丸,不建議使用。強(qiáng)烈建議使用有界隊(duì)列
https://blog.csdn.net/weixin_40304387/article/details/80508236? ?這篇文章很不錯(cuò)应结,對(duì)了解Executor框架有幫助刨疼。