Android多線程:線程池ThreadPool全面解析


前言

  • 對于多線程,大家應(yīng)該很熟悉。但是,大家了解線程池嗎?
  • 今天,我將帶大家全部學(xué)習(xí)關(guān)于線程池的所有知識。

Carson帶你學(xué)多線程系列
基礎(chǔ)匯總
Android多線程:基礎(chǔ)知識匯總
基礎(chǔ)使用
Android多線程:繼承Thread類使用(含實(shí)例教程)
Android多線程:實(shí)現(xiàn)Runnable接口使用(含實(shí)例教程)
復(fù)合使用
Android多線程:AsyncTask使用教程(含實(shí)例講解)
Android多線程:AsyncTask原理及源碼分析
Android多線程:HandlerThread使用教程(含實(shí)例講解)
Android多線程:HandlerThread原理及源碼分析
Android多線程:IntentService使用教程(含實(shí)例講解)
Android多線程:IntentService的原理及源碼分析
Android多線程:線程池ThreadPool全方位教學(xué)
相關(guān)使用
Android異步通信:這是一份全面&詳細(xì)的Handler機(jī)制學(xué)習(xí)攻略
Android多線程:手把手教你全面學(xué)習(xí)神秘的Synchronized關(guān)鍵字
Android多線程:帶你了解神秘的線程變量 ThreadLocal


目錄

示意圖

1. 簡介

示意圖

2. 工作原理

2.1 核心參數(shù)

  • 線程池中有6個(gè)核心參數(shù),具體如下
示意圖
  • 上述6個(gè)參數(shù)的配置 決定了 線程池的功能,具體設(shè)置時(shí)機(jī) = 創(chuàng)建 線程池類對象時(shí) 傳入
  1. ThreadPoolExecutor類 = 線程池的真正實(shí)現(xiàn)類
  2. 開發(fā)者可根據(jù)不同需求 配置核心參數(shù),從而實(shí)現(xiàn)自定義線程池
// 創(chuàng)建線程池對象如下
// 通過 構(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ì)說明

2.2 內(nèi)部原理邏輯

當(dāng)線程池運(yùn)行時(shí),遵循以下工作邏輯

示意圖

3. 使用流程

線程池的使用流程如下

// 1. 創(chuàng)建線程池
   // 創(chuàng)建時(shí),通過配置線程池的參數(shù),從而實(shí)現(xiàn)自己所需的線程池
   Executor threadPool = new ThreadPoolExecutor(
                                              CORE_POOL_SIZE,
                                              MAXIMUM_POOL_SIZE,
                                              KEEP_ALIVE,
                                              TimeUnit.SECONDS,
                                              sPoolWorkQueue,
                                              sThreadFactory
                                              );
    // 注:在Java中,已內(nèi)置4種常見線程池,下面會(huì)詳細(xì)說明

// 2. 向線程池提交任務(wù):execute()
    // 說明:傳入 Runnable對象
       threadPool.execute(new Runnable() {
            @Override
            public void run() {
                ... // 線程執(zhí)行任務(wù)
            }
        });

// 3. 關(guān)閉線程池shutdown() 
  threadPool.shutdown();
  
  // 關(guān)閉線程的原理
  // a. 遍歷線程池中的所有工作線程
  // b. 逐個(gè)調(diào)用線程的interrupt()中斷線程(注:無法響應(yīng)中斷的任務(wù)可能永遠(yuǎn)無法終止)

  // 也可調(diào)用shutdownNow()關(guān)閉線程:threadPool.shutdownNow()
  // 二者區(qū)別:
  // shutdown:設(shè)置 線程池的狀態(tài) 為 SHUTDOWN,然后中斷所有沒有正在執(zhí)行任務(wù)的線程
  // shutdownNow:設(shè)置 線程池的狀態(tài) 為 STOP,然后嘗試停止所有的正在執(zhí)行或暫停任務(wù)的線程,并返回等待執(zhí)行任務(wù)的列表
  // 使用建議:一般調(diào)用shutdown()關(guān)閉線程池;若任務(wù)不一定要執(zhí)行完,則調(diào)用shutdownNow()

4. 常見的4類功能線程池

根據(jù)參數(shù)的不同配置,Java中最常見的線程池有4類:

  • 定長線程池(FixedThreadPool
  • 定時(shí)線程池(ScheduledThreadPool
  • 可緩存線程池(CachedThreadPool
  • 單線程化線程池(SingleThreadExecutor

即 對于上述4類線程池,Java已根據(jù) 應(yīng)用場景 配置好核心參數(shù)

4.1 定長線程池(FixedThreadPool)

  • 特點(diǎn):只有核心線程 & 不會(huì)被回收、線程數(shù)量固定、任務(wù)隊(duì)列無大小限制(超出的線程任務(wù)會(huì)在隊(duì)列中等待)
  • 應(yīng)用場景:控制線程最大并發(fā)數(shù)
  • 具體使用:通過 Executors.newFixedThreadPool() 創(chuàng)建
  • 示例:
// 1. 創(chuàng)建定長線程池對象 & 設(shè)置線程池線程數(shù)量固定為3
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);

// 2. 創(chuàng)建好Runnable類線程對象 & 需執(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ù)量無限制(閑置時(shí)馬上回收)
  • 應(yīng)用場景:執(zhí)行定時(shí) / 周期性 任務(wù)
  • 使用:通過Executors.newScheduledThreadPool()創(chuàng)建
  • 示例:
// 1. 創(chuàng)建 定時(shí)線程池對象 & 設(shè)置線程池線程數(shù)量固定為5
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);

// 2. 創(chuàng)建好Runnable類線程對象 & 需執(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ù)量不固定(可無限大)、靈活回收空閑線程(具備超時(shí)機(jī)制,全部回收時(shí)幾乎不占系統(tǒng)資源)、新建線程(無線程可用時(shí))

任何線程任務(wù)到來都會(huì)立刻執(zhí)行,不需要等待

  • 應(yīng)用場景:執(zhí)行大量、耗時(shí)少的線程任務(wù)
  • 使用:通過Executors.newCachedThreadPool()創(chuàng)建
  • 示例:
// 1. 創(chuàng)建可緩存線程池對象
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

// 2. 創(chuàng)建好Runnable類線程對象 & 需執(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í)行,不需要處理線程同步的問題)

  • 應(yīng)用場景:不適合并發(fā)但可能引起IO阻塞性及影響UI線程響應(yīng)的操作,如數(shù)據(jù)庫操作,文件操作等

  • 使用:通過Executors.newSingleThreadExecutor()創(chuàng)建

  • 示例:

// 1. 創(chuàng)建單線程化線程池
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();

// 2. 創(chuàng)建好Runnable類線程對象 & 需執(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é) & 對比

示意圖

5. 總結(jié)

  • 閱讀本文后,相信你已經(jīng)非常了解線程池 & 用法
  • 下一篇文章我將對講解Android多線程的相關(guān)知識,感興趣的同學(xué)可以繼續(xù)關(guān)注Carson_Ho的簡書

Carson帶你學(xué)多線程系列
基礎(chǔ)匯總
Android多線程:基礎(chǔ)知識匯總
基礎(chǔ)使用
Android多線程:繼承Thread類使用(含實(shí)例教程)
Android多線程:實(shí)現(xiàn)Runnable接口使用(含實(shí)例教程)
復(fù)合使用
Android 多線程:AsyncTask使用教程(含實(shí)例講解)
Android 多線程:AsyncTask的原理及源碼分析
Android多線程:HandlerThread使用教程(含實(shí)例講解)
Android多線程:HandlerThread的原理及源碼分析
Android多線程:IntentService使用教程(含實(shí)例講解)
Android多線程:IntentService的原理及源碼分析
Android多線程:線程池ThreadPool全方位教學(xué)
相關(guān)使用
Android異步通信:這是一份全面&詳細(xì)的Handler機(jī)制學(xué)習(xí)攻略
Carson帶你學(xué)Java:手把手教你全面學(xué)習(xí)神秘的Synchronized關(guān)鍵字
Carson帶你學(xué)Java:帶你了解神秘的線程變量 ThreadLocal


歡迎關(guān)注Carson_Ho的簡書

不定期分享關(guān)于安卓開發(fā)的干貨,追求短、平、快,但卻不缺深度。


請點(diǎn)贊!因?yàn)槟愕墓膭?lì)是我寫作的最大動(dòng)力!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,716評論 25 709
  • 所有知識點(diǎn)已整理成app app下載地址 J2EE 部分: 1.Switch能否用string做參數(shù)? 在 Jav...
    侯蛋蛋_閱讀 2,700評論 1 4
  • 福建國學(xué)堂課前讀經(jīng)及開場溫馨提示 請帶讀經(jīng)及引導(dǎo)行禮的人員提前練習(xí): 一、讀經(jīng)(經(jīng)文讀音請務(wù)必掌握正確)。 二、引...
    荷荷花閱讀 990評論 0 0
  • 最憶是杭州(上) 第三天,我們的行程是靈隱寺、雷峰塔。靈隱寺是我們此行必去的一個(gè)景點(diǎn)。不僅是因?yàn)榛罘饾?jì)公,其實(shí)我們...
    孫小凌閱讀 825評論 4 5
  • 掐指一算, 一年已大半, 什么都沒干, 心里開始亂, 不知該咋辦, 當(dāng)機(jī)要立斷, 不然得完蛋!
    閑人日記閱讀 271評論 0 0

友情鏈接更多精彩內(nèi)容