完全解析Android多線程中線程池ThreadPool的原理和使用
前言對(duì)于多線程,大家應(yīng)該很熟悉。但是,大家了解線程池嗎?今天,我將帶大家全部學(xué)習(xí)關(guān)于線程池的所有知識(shí)。
目錄
1. 簡(jiǎn)介
2. 工作原理
2.1 核心參數(shù)線程池中有6個(gè)核心參數(shù),具體如下
上述6個(gè)參數(shù)的配置 決定了 線程池的功能,具體設(shè)置時(shí)機(jī) = 創(chuàng)建 線程池類(lèi)對(duì)象時(shí) 傳入
ThreadPoolExecutor類(lèi) = 線程池的真正實(shí)現(xiàn)類(lèi)
開(kāi)發(fā)者可根據(jù)不同需求 配置核心參數(shù),從而實(shí)現(xiàn)自定義線程池
// 創(chuàng)建線程池對(duì)象如下 // 通過(guò) 構(gòu)造方法 配置核心參數(shù) Executor executor = new ThreadPoolExecutor( CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory ); // 構(gòu)造函數(shù)源碼分析 public ThreadPoolExecutor (int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable workQueue>, ThreadFactory threadFactory )
注:Java 里已內(nèi)置4種常用的線程池(即 已經(jīng)配置好核心參數(shù)),下面會(huì)詳細(xì)說(shuō)明
2.2 內(nèi)部原理邏輯
當(dāng)線程池運(yùn)行時(shí),遵循以下工作邏輯
3. 使用流程
線程池的使用流程如下
// 1. 創(chuàng)建線程池 // 創(chuàng)建時(shí),通過(guò)配置線程池的參數(shù),從而實(shí)現(xiàn)自己所需的線程池 Executor threadPool = new ThreadPoolExecutor( CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory ); // 注:在Java中,已內(nèi)置4種常見(jiàn)線程池,下面會(huì)詳細(xì)說(shuō)明 // 2. 向線程池提交任務(wù):execute() // 說(shuō)明:傳入 Runnable對(duì)象 threadPool.execute(new Runnable() { @Override public void run() { ... // 線程執(zhí)行任務(wù) } }); // 3. 關(guān)閉線程池shutdown() threadPool.shutdown(); // 關(guān)閉線程的原理 // a. 遍歷線程池中的所有工作線程 // b. 逐個(gè)調(diào)用線程的interrupt()中斷線程(注:無(wú)法響應(yīng)中斷的任務(wù)可能永遠(yuǎn)無(wú)法終止) // 也可調(diào)用shutdownNow()關(guān)閉線程:threadPool.shutdownNow() // 二者區(qū)別: // shutdown:設(shè)置 線程池的狀態(tài) 為 SHUTDOWN,然后中斷所有沒(méi)有正在執(zhí)行任務(wù)的線程 // shutdownNow:設(shè)置 線程池的狀態(tài) 為 STOP,然后嘗試停止所有的正在執(zhí)行或暫停任務(wù)的線程,并返回等待執(zhí)行任務(wù)的列表 // 使用建議:一般調(diào)用shutdown()關(guān)閉線程池;若任務(wù)不一定要執(zhí)行完,則調(diào)用shutdownNow()
4. 常見(jiàn)的4類(lèi)功能線程池
根據(jù)參數(shù)的不同配置,Java中最常見(jiàn)的線程池有4類(lèi):
定長(zhǎng)線程池(FixedThreadPool)定時(shí)線程池(ScheduledThreadPool )可緩存線程池(CachedThreadPool)單線程化線程池(SingleThreadExecutor)
即 對(duì)于上述4類(lèi)線程池,Java已根據(jù) 應(yīng)用場(chǎng)景 配置好核心參數(shù)
4.1 定長(zhǎng)線程池(FixedThreadPool)特點(diǎn):只有核心線程 & 不會(huì)被回收、線程數(shù)量固定、任務(wù)隊(duì)列無(wú)大小限制(超出的線程任務(wù)會(huì)在隊(duì)列中等待)應(yīng)用場(chǎng)景:控制線程最大并發(fā)數(shù)具體使用:通過(guò) Executors.newFixedThreadPool() 創(chuàng)建示例:
// 1. 創(chuàng)建定長(zhǎng)線程池對(duì)象 & 設(shè)置線程池線程數(shù)量固定為3 ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3); // 2. 創(chuàng)建好Runnable類(lèi)線程對(duì)象 & 需執(zhí)行的任務(wù) Runnable task =new Runnable(){ public void run(){ System.out.println("執(zhí)行任務(wù)啦"); } }; // 3. 向線程池提交任務(wù):execute() fixedThreadPool.execute(task); // 4. 關(guān)閉線程池 fixedThreadPool.shutdown();
4.2 定時(shí)線程池(ScheduledThreadPool )特點(diǎn):核心線程數(shù)量固定、非核心線程數(shù)量無(wú)限制(閑置時(shí)馬上回收)應(yīng)用場(chǎng)景:執(zhí)行定時(shí) / 周期性 任務(wù)使用:通過(guò)Executors.newScheduledThreadPool()創(chuàng)建示例:
// 1. 創(chuàng)建 定時(shí)線程池對(duì)象 & 設(shè)置線程池線程數(shù)量固定為5 ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5); // 2. 創(chuàng)建好Runnable類(lèi)線程對(duì)象 & 需執(zhí)行的任務(wù) Runnable task =new Runnable(){ public void run(){ System.out.println("執(zhí)行任務(wù)啦"); } }; // 3. 向線程池提交任務(wù):schedule() scheduledThreadPool.schedule(task, 1, TimeUnit.SECONDS); // 延遲1s后執(zhí)行任務(wù) scheduledThreadPool.scheduleAtFixedRate(task,10,1000,TimeUnit.MILLISECONDS);// 延遲10ms后、每隔1000ms執(zhí)行任務(wù) // 4. 關(guān)閉線程池 scheduledThreadPool.shutdown();
4.3 可緩存線程池(CachedThreadPool)特點(diǎn):只有非核心線程、線程數(shù)量不固定(可無(wú)限大)、靈活回收空閑線程(具備超時(shí)機(jī)制,全部回收時(shí)幾乎不占系統(tǒng)資源)、新建線程(無(wú)線程可用時(shí))
任何線程任務(wù)到來(lái)都會(huì)立刻執(zhí)行,不需要等待
應(yīng)用場(chǎng)景:執(zhí)行大量、耗時(shí)少的線程任務(wù) 使用:通過(guò)Executors.newCachedThreadPool()創(chuàng)建 示例:
// 1. 創(chuàng)建可緩存線程池對(duì)象 ExecutorService cachedThreadPool = Executors.newCachedThreadPool(); // 2. 創(chuàng)建好Runnable類(lèi)線程對(duì)象 & 需執(zhí)行的任務(wù) Runnable task =new Runnable(){ public void run(){ System.out.println("執(zhí)行任務(wù)啦"); } }; // 3. 向線程池提交任務(wù):execute() cachedThreadPool.execute(task); // 4. 關(guān)閉線程池 cachedThreadPool.shutdown(); //當(dāng)執(zhí)行第二個(gè)任務(wù)時(shí)第一個(gè)任務(wù)已經(jīng)完成 //那么會(huì)復(fù)用執(zhí)行第一個(gè)任務(wù)的線程,而不用每次新建線程。
4.4 單線程化線程池(SingleThreadExecutor)
特點(diǎn):只有一個(gè)核心線程(保證所有任務(wù)按照指定順序在一個(gè)線程中執(zhí)行,不需要處理線程同步的問(wèn)題)
應(yīng)用場(chǎng)景:不適合并發(fā)但可能引起IO阻塞性及影響UI線程響應(yīng)的操作,如數(shù)據(jù)庫(kù)操作,文件操作等
使用:通過(guò)Executors.newSingleThreadExecutor()創(chuàng)建示例:
// 1. 創(chuàng)建單線程化線程池 ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor(); // 2. 創(chuàng)建好Runnable類(lèi)線程對(duì)象 & 需執(zhí)行的任務(wù) Runnable task =new Runnable(){ public void run(){ System.out.println("執(zhí)行任務(wù)啦"); } }; // 3. 向線程池提交任務(wù):execute() singleThreadExecutor.execute(task); // 4. 關(guān)閉線程池 singleThreadExecutor.shutdown();
4.5 常見(jiàn)線程池 總結(jié) & 對(duì)比
5. 總結(jié)閱讀本文后,相信你已經(jīng)非常了解線程池 & 用法接下來(lái),我會(huì)繼續(xù)講解Android開(kāi)發(fā)中關(guān)于多線程的知識(shí),具體包括Thread類(lèi)、Handler、HandlerThread等等,有興趣可以繼續(xù)關(guān)注Carson_Ho的安卓開(kāi)發(fā)筆記請(qǐng)幫頂 / 評(píng)論點(diǎn)贊!因?yàn)槟愕墓膭?lì)是我寫(xiě)作的最大動(dòng)力!
相關(guān)文章
Android自定義ViewGroup實(shí)現(xiàn)絢麗的仿支付寶咻一咻雷達(dá)脈沖效果
這篇文章主要介紹了Android自定義ViewGroup實(shí)現(xiàn)絢麗的仿支付寶咻一咻雷達(dá)脈沖效果的相關(guān)資料,需要的朋友可以參考下2016-10-10SurfaceView實(shí)現(xiàn)紅包雨平移動(dòng)畫(huà)
這篇文章主要為大家詳細(xì)介紹了SurfaceView實(shí)現(xiàn)紅包雨平移動(dòng)畫(huà),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07Android提高之多方向抽屜實(shí)現(xiàn)方法
這篇文章主要介紹了Android的多方向抽屜實(shí)現(xiàn)方法,有一定的實(shí)用價(jià)值,需要的朋友可以參考下2014-08-08Android 修改viewpage滑動(dòng)速度的實(shí)現(xiàn)代碼
由于Viewpager的滑動(dòng)速度是固定的,所以很頭疼,下面小編通過(guò)實(shí)例代碼給大家分享android 修改viewpage滑動(dòng)速度的方法,需要的朋友參考下吧2017-09-09Android中Fragment的基本用法示例總結(jié)
Fragment是activity的界面中的一部分或一種行為,下面這篇文章主要給大家介紹了關(guān)于Android中Fragment的基本用法的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2018-05-05Android 開(kāi)發(fā)使用PopupWindow實(shí)現(xiàn)彈出警告框的復(fù)用類(lèi)示例
這篇文章主要介紹了Android 開(kāi)發(fā)使用PopupWindow實(shí)現(xiàn)彈出警告框的復(fù)用類(lèi),結(jié)合實(shí)例形式分析了Android基于PopupWindow彈出警告框的復(fù)用類(lèi)具體布局與功能實(shí)現(xiàn)技巧,需要的朋友可以參考下2020-05-05Android打空包后提示沒(méi)有"android:exported"的屬性設(shè)置問(wèn)題解決
這篇文章主要介紹了Android打空包后提示沒(méi)有"android:exported"的屬性設(shè)置問(wèn)題的解決方法,文中通過(guò)圖文將解決的辦法介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2023-02-02Android內(nèi)置SQLite的使用詳細(xì)介紹
這篇文章主要介紹了Android內(nèi)置SQLite的使用詳細(xì)介紹,文章通過(guò)文章展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-09-09Android實(shí)現(xiàn)自定義滑動(dòng)式抽屜菜單效果
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)自定義滑動(dòng)式抽屜效果菜單,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-05-05