淺談Java線程池是如何運(yùn)行的
異步編程工具在Android開(kāi)發(fā)中目前最被推薦的就是Kotlin協(xié)程,在引入Kotlin協(xié)程機(jī)制前,除了響應(yīng)式擴(kuò)展(RxJava)兼任異步編程工具外,Java API中線程與線程池就是最重要異步編程手段。而對(duì)于Android平臺(tái)的Kotlin協(xié)程實(shí)現(xiàn)來(lái)說(shuō),依然使用的是線程池來(lái)作為任務(wù)執(zhí)行的載體,所以可以將Android平臺(tái)的Kotlin協(xié)程簡(jiǎn)單的理解是對(duì)線程池的一種高度封裝。
Executors.newFixedThreadPool(10).asCoroutineDispatcher() Dispatchers.IO.asExecutor()
因此我們先了解Java線程池是如何運(yùn)行的,再深入理解Kotlin協(xié)程是如何實(shí)現(xiàn)的。
從Thread到Executor
線程的創(chuàng)建通過(guò)Thread類,為了復(fù)用線程而進(jìn)行池化就有了線程池。線程池帶來(lái)了兩點(diǎn)明顯優(yōu)勢(shì):
- 降低重復(fù)創(chuàng)建線程的開(kāi)銷
- 將任務(wù)與線程管理解耦
Executor接口就是第二點(diǎn)的體現(xiàn)。其execute方法用于執(zhí)行任務(wù),不必關(guān)系這個(gè)任務(wù)執(zhí)行的載體究竟是什么,到底有沒(méi)有創(chuàng)建線程。ThreadPoolExecutor實(shí)現(xiàn)類就是這個(gè)任務(wù)執(zhí)行器的線程池實(shí)現(xiàn)。
ThreadPoolExecutor的任務(wù)添加與線程復(fù)用
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}//1
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}//2
else if (!addWorker(command, false))
reject(command);//3
}
查看execute方法可以清楚了解其運(yùn)行方式:
- 當(dāng)線程數(shù)小于corePoolSize時(shí),創(chuàng)建線程并執(zhí)行任務(wù);
- 若任務(wù)未通過(guò)步驟1添加,則入隊(duì)workQueue;(主要邏輯在if的條件判斷中,而if內(nèi)的邏輯處理的是在一些異常下,對(duì)入隊(duì)的回滾或補(bǔ)充創(chuàng)建線程)
- 若任務(wù)未入隊(duì),則仍創(chuàng)建線程(上限為maximumPoolSize)并執(zhí)行任務(wù),失敗則執(zhí)行拒絕策略。
boolean addWorker(Runnable firstTask, boolean core)就是創(chuàng)建線程的方法,方法中第二個(gè)參數(shù)代表以corePoolSize還是maximumPoolSize為界,方法內(nèi)其余創(chuàng)建線程的細(xì)節(jié)邏輯不深究。但要關(guān)注一下線程的封裝類Worker,addWorker方法內(nèi)調(diào)用了Worker內(nèi)被封裝線程的start方法,執(zhí)行Worker的run方法。我們將run方法內(nèi)的runWorker簡(jiǎn)化如下:
void runWorker(Worker w) {
Runnable task = w.firstTask;
w.firstTask = null;
while (task != null || (task = getTask()) != null) {
task.run();
}
}
可以發(fā)現(xiàn),初始任務(wù)執(zhí)行完后,不斷通過(guò)getTask方法獲取任務(wù)執(zhí)行,以此來(lái)實(shí)現(xiàn)線程的復(fù)用,而不是只執(zhí)行完一個(gè)任務(wù)就銷毀了線程。
另外查看簡(jiǎn)化后的getTask方法如下:
private Runnable getTask() {
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
try {
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();
if (r != null)
return r;
} catch (InterruptedException retry) { }
}
任務(wù)是從阻塞隊(duì)列workQueue中取出的,并且根據(jù)配置allowCoreThreadTimeOut與線程個(gè)數(shù)是否大于corePoolSize,來(lái)決定使用BlockingQueue<Runable>的帶超時(shí)時(shí)間的取任務(wù)方法poll,還是阻塞取任務(wù)方法take,以實(shí)現(xiàn)任務(wù)列表為空時(shí)適時(shí)銷毀線程還是阻塞線程。
回過(guò)頭來(lái)看ThreadPoolExecutor的構(gòu)造方法:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
我們可以清楚的明白每個(gè)參數(shù)的含義,以及它是如何影響線程池中線程的復(fù)用了。
到此這篇關(guān)于淺談Java線程池是如何運(yùn)行的的文章就介紹到這了,更多相關(guān)Java 線程池內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Java簡(jiǎn)單實(shí)現(xiàn)線程池
- Java多線程之線程池七個(gè)參數(shù)詳解
- Java利用線程工廠監(jiān)控線程池的實(shí)現(xiàn)示例
- Java 使用線程池執(zhí)行多個(gè)任務(wù)的示例
- 深入理解Java線程池從設(shè)計(jì)思想到源碼解讀
- 教你如何監(jiān)控 Java 線程池運(yùn)行狀態(tài)的操作(必看)
- java高級(jí)應(yīng)用:線程池的全面講解(干貨)
- java多線程CountDownLatch與線程池ThreadPoolExecutor/ExecutorService案例
- java 線程池keepAliveTime的含義說(shuō)明
- java并發(fā)包中CountDownLatch和線程池的使用詳解
- Java 線程池的作用以及該如何使用
- Java并發(fā)線程之線程池的知識(shí)總結(jié)
- Java線程池配置的一些常見(jiàn)誤區(qū)總結(jié)
- Java ExecutorServic線程池異步實(shí)現(xiàn)流程
- java 優(yōu)雅關(guān)閉線程池的方案
- java中常見(jiàn)的6種線程池示例詳解
- 淺談Java線程池的7大核心參數(shù)
相關(guān)文章
SpringBoot 導(dǎo)出數(shù)據(jù)生成excel文件返回方式
這篇文章主要介紹了SpringBoot 導(dǎo)出數(shù)據(jù)生成excel文件返回方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-10-10
java調(diào)用微信現(xiàn)金紅包接口的心得與體會(huì)總結(jié)
這篇文章主要介紹了java調(diào)用微信現(xiàn)金紅包接口的心得與體會(huì)總結(jié),有需要的朋友可以了解一下。2016-11-11
Springboot在有參構(gòu)造方法類中使用@Value注解取值
這篇文章主要介紹了Springboot在有參構(gòu)造方法類中使用@Value注解取值,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-06-06
idea快速搭建springboot項(xiàng)目的操作方法
下面小編就為大家分享一篇idea快速搭建springboot項(xiàng)目的操作方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2017-12-12
使用javax.sound實(shí)現(xiàn)簡(jiǎn)單音頻播放
這篇文章主要為大家詳細(xì)介紹了使用javax.sound實(shí)現(xiàn)簡(jiǎn)單音頻播放,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-03-03

