Android-Threadpool

? ? ?關于線程我不想再說什么,感興趣的同學可以看我之前寫過的一篇文章:Android-多線程,這里對線程有一個比較詳細的解釋。

Android-多線程 - 簡書

我們今天直入重點:聊意料我們常用的線程池.

一:

1.什么是線程池?

聽名字也不難理解,線程池就是線程的集合,用來控制管理線程,控制并發(fā)數(shù)等,減少了線程創(chuàng)建和銷毀的次數(shù)。提高線程的復用率,降低性能的損耗。

2.有哪些線程池呢?

? ? ? ? 首先我們先從源碼的角度開始分析,先創(chuàng)建一個線程池,然后一步步查看它的源碼,分析其關系。

? ? ? ? 直接上圖:


然后一步步查看:從最上面的接口開始。


首先。Executor是一個類的實現(xiàn)接口,里面有一個執(zhí)行方法:execute().,這就是線程池的起源,屬于線程的一個執(zhí)行工具,并不是真正的線程池。


如圖,我們可以看到ExecutorService接口繼承自我們之前的Executor工具類,它里面有好多的api方法,是真正的線程池接口。


然后呢,AbstractExecutorService是一個抽象方法,它實現(xiàn)了ExecutorService接口,可以實現(xiàn)其抽象方法, 也可以進行自定義。


最后ThreadPoolExecutor才是我們的具體實現(xiàn)類,Android中的線程池都是 直接或間接通過配置ThreadPoolExecutor 來實現(xiàn)不同的線程池。

我們來看一下它的構造方法:



? 其實ThreadPoolExecutor有四種構造方法,我們舉例其中最多的一個講一下。

(1)? //核心線程數(shù)?

int corePoolSize, ?

注:線程池新建線程的時候,如果當前線程總數(shù)小于 corePoolSize ,則新建的是核心線程;如果超過corePoolSize,則新建的是非核心線程。

(2)? //最大線程數(shù),活動線程數(shù)量超過它,后續(xù)任務就會自動排隊 ? ? ? ? ? ? ? ? ? ?

int maximumPoolSize

線程總數(shù)= 核心線程數(shù) + 非核心線程數(shù)。

(3)? ? //超時時長,非核心線程如果長時間閑置,超過這個時長便被回收? ? ,但如果設置allowCoreThreadTimeOut = true,則會作用于核心線程?,超過時長也會被回收。??

long keepAliveTime, ? ? ? ? ? ? ? ? ? ? ? ? ? ?

(4)? ?//枚舉類型,設置keepAliveTime的單位,MILLISECONDS : 毫秒 、SECONDS : 秒、MINUTES : 分、HOURS : 小時、DAYS : 天

TimeUnit unit, ?

//緩沖任務隊列,線程池的execute方法會將Runnable對象存儲起來,當所有的核心線程都有活干,新添加的任務會被添加到這個隊列中等待處理,如果隊列滿了,則新建非核心線程執(zhí)行任務。

BlockingQueue workQueue, ?

(5)? //線程工廠接口,只有一個new Thread(Runnable r)方法,可以認為是線程池創(chuàng)建新線程 ?

BlockingQueue有四種隊列類型:(1)SynchronousQueue:(同步隊列)

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (2)LinkedBlockingQueue(鏈表阻塞隊列)

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (3)ArrayBlockingQueue(數(shù)組阻塞隊列)

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (4)DelayQueue(延遲隊列)

SynchronousQueue:(同步隊列)這個隊列接收到任務的時候,會直接提交給線程處理,而不保留它,但如果所有的線程都在工作呢?這種情況下,SynchronousQueue就會新建一個線程來處理這個任務。所以為了保證不出現(xiàn)(線程數(shù)達到了maximumPoolSize而不能新建線程)的錯誤,使用這個類型隊列的時候,maximumPoolSize一般指定成Integer.MAX_VALUE,即無限大,去規(guī)避這個使用風險。

LinkedBlockingQueue(鏈表阻塞隊列):這個隊列接收到任務的時候,如果當前線程數(shù)小于核心線程數(shù),則新建線程(核心線程)處理任務;如果當前線程數(shù)等于核心線程數(shù),則進入隊列等待。由于這個隊列沒有最大值限制,即所有超過核心線程數(shù)的任務都將被添加到隊列中,這也就導致了maximumPoolSize的設定失效,因為總線程數(shù)永遠不會超過corePoolSize

ArrayBlockingQueue(數(shù)組阻塞隊列):可以限定隊列的長度(既然是數(shù)組,那么就限定了大?。?,接收到任務的時候,如果沒有達到corePoolSize的值,則新建線程(核心線程)執(zhí)行任務,如果達到了,則入隊等候,如果隊列已滿,則新建線程(非核心線程)執(zhí)行任務,又如果總線程數(shù)到了maximumPoolSize,并且隊列也滿了,則發(fā)生錯誤

DelayQueue(延遲隊列):隊列內(nèi)元素必須實現(xiàn)Delayed接口,這就意味著你傳進去的任務必須先實現(xiàn)Delayed接口。這個隊列接收到任務時,首先先入隊,只有達到了指定的延時時間,才會執(zhí)行任務

(6)? ?//創(chuàng)建線程的方式

? ? ? ?ThreadFactory threadFactory? 這是一個接口,new它的時候需要實現(xiàn)他的Thread newThread(Runnable r)方法。

(7)? ?//?這個主要是用來拋異常的,如果線程無法執(zhí)行新任務一般會拋一個RejectedExecutionException異常。

? ? ? ?RejectedExecutionHandler handler

二:ok,講完了這些,我們來看看如何使用線程池?


線程池新添加了任務,那么線程池是如何運行的呢,總結:

1:如果線程數(shù)量未達到corePoolSize,則新建一個線程(核心線程)執(zhí)行任務

2:如果線程數(shù)量達到了corePools,則將任務移入隊列等待

3:如果隊列已滿,新建線程(非核心線程)執(zhí)行任務

4:如果隊列已滿,總線程數(shù)又達到了maximumPoolSize,就會由RejectedExecutionHandler拋出異常


但我們不需要這么費勁,java已經(jīng)給我們提供了四種線程池,,來搞一下。

第一種:

A:定長線程池? newFixedThreadPool ,只有核心線程,數(shù)量固定,不會被回收??煽刂凭€程最大并發(fā)數(shù),超出的線程會在隊列中等待。其中nThreads參數(shù)是我們要創(chuàng)建幾個線程。如果所有線程都出于運行狀態(tài),提交額外的任務,他們會在隊列中等待,直到有一個線程可用為止。

使用:


第二種:

B:緩存線程池 newCacheThreadPool,只有非核心線程,最大線程數(shù)不做限制,如果線程池長度超過處理需要,可靈活回收空閑線程,若無可回收,則新建線程??臻e線程超過60秒會被終止并從線程池里移除緩存。

使用:


第三種:

C:定長任務線程池,ScheduledExecutorService.支持定時及周期性任務執(zhí)行。

corePoolSize 參數(shù)是指在池中保留的線程數(shù),即使它們是空閑的。這個函數(shù)最終會返回一個新創(chuàng)建的調(diào)度線程池.

使用:


第四種:

? ? D:newSingleThreadExecutor?創(chuàng)建一個單線程的線程池,用唯一的工作線程來執(zhí)行任務,保證所有任務按照指定順序(FIFO, LIFO, 優(yōu)先級)執(zhí)行。如果這個單獨的線程終止是因為在執(zhí)行前異?;蛘呓K止,若需要執(zhí)行后續(xù)的任務,那么就需要一個新的去替代它,返回的是一個重新創(chuàng)建的單線程去執(zhí)行。

使用:

突然覺得直接寫用法,不來個demo,是不是小伙伴不容易理解呀。那好。我們以緩存線程池為例.來個場景演示。大家都知道下載文件吧,我們就整這個。多線程下載多個文件。

? ? 上一波圖:

? ? ? ? 咳咳,初始化UI就.......省了吧。




效果:


點擊下載文件可以看到是同一個線程池,兩個線程平行。


文件A和文件C是同一個線程在下載,也就是在線程thread-1下載文件A完畢后,點擊下載文件C,并沒有在重新在創(chuàng)建線程,而是復用了文件A下載的thread-1繼續(xù)下載文件C。

好了就這么多,拜拜。

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

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

  • 為什么使用線程池 當我們在使用線程時,如果每次需要一個線程時都去創(chuàng)建一個線程,這樣實現(xiàn)起來很簡單,但是會有一個問題...
    閩越布衣閱讀 4,420評論 10 45
  • 圖片發(fā)自簡書App 寫給所有在大學里迷茫失敗的人 有一個話題無論在簡書、在知乎、在貼吧、在各種網(wǎng)絡平臺和實體書市場...
    月藏烏山鳥閱讀 260評論 1 5
  • “管理者的另一把權杖:非職權影響力” 做好自己,影響他人。做人,首先自己要正。進而形成一種文化。
    自如得己閱讀 112評論 0 0
  • 2018年3月8日陰 自從入冬一來,流感肆虐,我也未能幸免。纏纏綿綿,至今也沒有全愈。 想到年輕時,感冒都不帶吃藥...
    習習涼風過閱讀 219評論 0 1
  • 如果說,懷念是一片海,那么我的心早已浩瀚一片。如果說,眷戀是一灣月,那么我的心已是月光漫天。如果說,愛是我心上的一...
    riyueqin閱讀 447評論 0 2

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