欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

android線程池,Android線程池面試題

Android中的線程池

線程池的好處

做網(wǎng)站、網(wǎng)站設(shè)計(jì)過程中,需要針對(duì)客戶的行業(yè)特點(diǎn)、產(chǎn)品特性、目標(biāo)受眾和市場(chǎng)情況進(jìn)行定位分析,以確定網(wǎng)站的風(fēng)格、色彩、版式、交互等方面的設(shè)計(jì)方向。創(chuàng)新互聯(lián)建站還需要根據(jù)客戶的需求進(jìn)行功能模塊的開發(fā)和設(shè)計(jì),包括內(nèi)容管理、前臺(tái)展示、用戶權(quán)限管理、數(shù)據(jù)統(tǒng)計(jì)和安全保護(hù)等功能。

1、重用線程池中的線程,避免線程的創(chuàng)建與銷毀帶來的性能開銷

2、能有效控制線程池的最大并發(fā)數(shù),避免大量線程因搶占資源而導(dǎo)致的阻塞

3、能對(duì)線程進(jìn)行簡(jiǎn)單的管理,提供定時(shí)或者指定間隔時(shí)間、循環(huán)執(zhí)行等操作

線程池的概率來自于java的Executor接口,實(shí)現(xiàn)類是ThreadPoolExecutor, 它提供一系列的參數(shù)來配置線程池,以此構(gòu)建不同的線程池。Android的線程池分4類,都是通過Executors所提供的工廠方法來得到。

ThreadPoolExecutor有四個(gè)構(gòu)造函數(shù),下面這個(gè)是最常用的

public?ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueueRunnnable workQueue, ThreadFactory threadFactory)

corePoolSize

線程池中的核心線程數(shù),默認(rèn)情況下核心線程會(huì)在線程池中一直存活,即使他們處于閑置狀態(tài)。如果設(shè)置ThreadPoolExecutor 中的allowCoreThreadTimeOut = true, 核心線程在等待新任務(wù)到來時(shí)有超時(shí)機(jī)制,時(shí)間超過keepAliveTime所指定的時(shí)間后,核心線程會(huì)終止。

maximumPoolSize

最大線程數(shù)

keepAliveTime

非核心線程閑置的超時(shí)時(shí)間,超過這個(gè)時(shí)間,非核心線程會(huì)被回收。核心線程則要看allowCoreThreadTimeOut屬性的值。

unit

時(shí)間單位

workQueue

線程池中的工作隊(duì)列

threadFactory

線程工廠,為線程池提供創(chuàng)建新線程的功能。

舉個(gè)例子,我們常用的okhttp內(nèi)部也是使用了線程池,它的ThreadPoolExecutor主要是定義在Dispatcher類里面。 使用的是CachedThreadPool。

executorService = ThreadPoolExecutor(0, Int.MAX_VALUE, 60, TimeUnit.SECONDS, SynchronousQueue(), ThreadFactory("okhttp Dispatcher", false))

1、FixedThreadPool

通過Executors的newFixedThreadPool()創(chuàng)建,這是一個(gè)線程數(shù)量固定的線程池,里面所有的線程都是核心線程。

public static ExecutorService newFixedThreadPool(int nThreads){

return new ThreadPoolExecutor(nThreads, nThreads, 0, TimeUnit.MILLISECONDS, new LinkedBlockingQueueRunnable())

}

2、CachedThreadPool

通過Executors的newCacheThreadPool()創(chuàng)建,這是一個(gè)線程數(shù)量不定的線程池,里面所有的線程都是非核心線程。最大線程數(shù)是無限大,當(dāng)線程池中的線程都處于活動(dòng)狀態(tài)時(shí),新的task會(huì)創(chuàng)建新的線程來處理,否則就使用空閑的線程處理,所有的線程都是60s的超時(shí)時(shí)間,超時(shí)后會(huì)自動(dòng)回收。

public static ExecutorService?newFixedThreadPool(){

return new ThreadPoolExecutor(0,?Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueueRunnable())

}

3、ScheduledThreadPool

通過Executors的newScheduledThreadPool()創(chuàng)建, 核心線程固定,非核心線程無限大,當(dāng)非核心線程空閑時(shí),會(huì)立即被回收。適合做定時(shí)任務(wù)或者固定周期的重復(fù)任務(wù)。

public static ExecutorService?newScheduledThreadPool(int corePoolSize){

return new ThreadPoolExecutor(corePoolSize,?Integer.MAX_VALUE, 0, TimeUnit.SECONDS, new DelayedWorkQueue())

}

4、SingleThreadExcecutor

通過Executors的newSingleThreadPool()創(chuàng)建,內(nèi)部只有一個(gè)核心線程。

public static ExecutorService?newFixedThreadPool(){

return new ThreadPoolExecutor(1,?1, 0, TimeUnit.MILLISECONDS, new LinkedBlockingQueueRunnable())

}

課外知識(shí):LinkedBlockingQueue

LinkedBlockingQueue是由鏈表組成的阻塞隊(duì)列,內(nèi)部head 指向隊(duì)列第一個(gè)元素,last指向最后一個(gè)元素。入隊(duì)和出隊(duì)都會(huì)加鎖阻塞,都是使用了不同的鎖。

DelayedWorkQueue

延時(shí)隊(duì)列,隊(duì)內(nèi)元素必須是Delayed的實(shí)現(xiàn)類。對(duì)內(nèi)元素會(huì)按照Delayed時(shí)間進(jìn)行排序,對(duì)內(nèi)元素只有在delayed時(shí)間過期了才能出隊(duì)。

入隊(duì)的時(shí)候不阻塞隊(duì)列,出隊(duì)的時(shí)候,如果隊(duì)列為空或者隊(duì)列里所有元素都等待時(shí)間都沒有到期,則該線程進(jìn)入阻塞狀態(tài)。

Android多線程的四種方式:Handler、AsyncTask、ThreadPoolExector、IntentService

異步通信機(jī)制,將工作線程中需更新UI的操作信息 傳遞到 UI主線程,從而實(shí)現(xiàn) 工作線程對(duì)UI的更新處理,最終實(shí)現(xiàn)異步消息的處理。Handler不僅僅能將子線程的數(shù)據(jù)傳遞給主線程,它能實(shí)現(xiàn)任意兩個(gè)線程的數(shù)據(jù)傳遞。

(1)Message

Message 可以在線程之間傳遞消息。可以在它的內(nèi)部攜帶少量數(shù)據(jù),用于在不同線程之間進(jìn)行數(shù)據(jù)交換。除了 what 字段,還可以使用 arg1 和 arg2 來攜帶整型數(shù)據(jù),使用 obj 來攜帶 Object 數(shù)據(jù)。

(2) Handler

Handler 作為處理中心,用于發(fā)送(sendMessage 系列方法)與處理消息(handleMessage 方法)。

(3) MessageQueue

MessageQueue 用于存放所有通過 Handler 發(fā)送的消息。這部分消息會(huì)一直存放在消息隊(duì)列中,直到被處理。每個(gè)線程中只會(huì)有一個(gè) MessageQueue 對(duì)象

(4) Looper

Looper 用于管理 MessageQueue 隊(duì)列,Looper對(duì)象通過loop()方法開啟了一個(gè)死循環(huán)——for (;;){},不斷地從looper內(nèi)的MessageQueue中取出Message,并傳遞到 Handler 的 handleMessage() 方法中。每個(gè)線程中只會(huì)有一個(gè) Looper 對(duì)象。

AsyncTask 是一種輕量級(jí)的任務(wù)異步類,可以在后臺(tái)子線程執(zhí)行任務(wù),且將執(zhí)行進(jìn)度及執(zhí)行結(jié)果傳遞給 UI 線程。

(1)onPreExecute()

在 UI 線程上工作,在任務(wù)執(zhí)行 doInBackground() 之前調(diào)用。此步驟通常用于設(shè)置任務(wù),例如在用戶界面中顯示進(jìn)度條。

(2)doInBackground(Params... params)

在子線程中工作,在 onPreExecute() 方法結(jié)束后執(zhí)行,這一步被用于在后臺(tái)執(zhí)行長時(shí)間的任務(wù),Params 參數(shù)通過 execute(Params) 方法被傳遞到此方法中。任務(wù)執(zhí)行結(jié)束后,將結(jié)果傳遞給 onPostExecute(Result) 方法,同時(shí)我們可以通過 publishProgress(Progress) 方法,將執(zhí)行進(jìn)度發(fā)送給 onProgressUpdate(Progress) 方法。

(3)onProgressUpdate(Progress... values)

在 UI 線程上工作,會(huì)在 doInBackground() 中調(diào)用 publishProgress(Progress) 方法后執(zhí)行,此方法用于在后臺(tái)計(jì)算仍在執(zhí)行時(shí)(也就是 doInBackgound() 還在執(zhí)行時(shí))將計(jì)算執(zhí)行進(jìn)度通過 UI 顯示出來。例如,可以通過動(dòng)畫進(jìn)度條或顯示文本字段中的日志,從而方便用戶知道后臺(tái)任務(wù)執(zhí)行的進(jìn)度。

(4)onPostExecute(Result result)

在 UI 線程上工作,在任務(wù)執(zhí)行完畢(即 doInBackground(Result) 執(zhí)行完畢)并將執(zhí)行結(jié)果傳過來的時(shí)候工作。

使用規(guī)則:

(1)AsyncTask 是個(gè)抽象類,所以要?jiǎng)?chuàng)建它的子類實(shí)現(xiàn)抽象方法

(1)AsyncTask 類必須是在 UI 線程中被加載,但在Android 4.1(API 16)開始,就能被自動(dòng)加載完成。

(2)AsyncTask 類的實(shí)例對(duì)象必須在 UI 線程中被創(chuàng)建。

(3)execute() 方法必須是在 UI 線程中被調(diào)用。

(4)不要手動(dòng)調(diào)用方法 onPreExecute()、onPostExecute()、doInBackground()、onProgressUpdate()

(5)任務(wù)只能執(zhí)行一次(如果嘗試第二次執(zhí)行,將拋出異常)。即一個(gè)AsyncTask對(duì)象只能調(diào)用一次execute()方法。

原理:

? ? ? 其源碼中原理還是 Thread 與 Handler 的實(shí)現(xiàn),其包含 兩個(gè)線程池,一個(gè) Handler,如下所示:

名稱類型作用

SERIAL_EXECUTOR線程池分發(fā)任務(wù),串行分發(fā),一次只分發(fā)一個(gè)任務(wù)

THREAD_POOL_EXECUTOR線程池執(zhí)行任務(wù),并行執(zhí)行,執(zhí)行的任務(wù)由 SERIAL_EXECUTOR 分發(fā)

InternalHandlerHandler負(fù)責(zé)子線程與主線程的溝通,通知主線程做 UI 工作

一方面減少了每個(gè)并行任務(wù)獨(dú)自建立線程的開銷,另一方面可以管理多個(gè)并發(fā)線程的公共資源,從而提高了多線程的效率。所以ThreadPoolExecutor比較適合一組任務(wù)的執(zhí)行。Executors利用工廠模式對(duì)ThreadPoolExecutor進(jìn)行了封裝。

Executors提供了四種創(chuàng)建ExecutorService的方法,他們的使用場(chǎng)景如下:

1. Executors.newFixedThreadPool()

創(chuàng)建一個(gè)定長的線程池,每提交一個(gè)任務(wù)就創(chuàng)建一個(gè)線程,直到達(dá)到池的最大長度,這時(shí)線程池會(huì)保持長度不再變化。

當(dāng)線程處于空閑狀態(tài)時(shí),它們并不會(huì)被回收,除非線程池被關(guān)閉。當(dāng)所有的線程都處于活動(dòng)狀態(tài)時(shí),新任務(wù)都會(huì)處于等待狀態(tài),直到有線程空閑出來。

只有核心線程并且不會(huì)被回收,能夠更加快速的響應(yīng)外界的請(qǐng)求。

2. Executors.newCachedThreadPool()

創(chuàng)建一個(gè)可緩存的線程池,如果當(dāng)前線程池的長度超過了處理的需要時(shí),它可以靈活的回收空閑的線程,當(dāng)需要增加時(shí),它可以靈活的添加新的線程,而不會(huì)對(duì)池的長度作任何限制

線程數(shù)量不定的線程池,只有非核心線程,最大線程數(shù)為 Integer.MAX_VALUE。當(dāng)線程池中的線程都處于活動(dòng)狀態(tài)時(shí),線程池會(huì)創(chuàng)建新的線程來處理新任務(wù),否則利用空閑的線程來處理新任務(wù)。線程池中的空閑線程具有超時(shí)機(jī)制,為 60s。

任務(wù)隊(duì)列相當(dāng)于一個(gè)空集合,導(dǎo)致任何任務(wù)都會(huì)立即被執(zhí)行,適合執(zhí)行大量耗時(shí)較少的任務(wù)。當(dāng)整個(gè)線程池都處于限制狀態(tài)時(shí),線程池中的線程都會(huì)超時(shí)而被停止。

3. Executors.newScheduledThreadPool()

創(chuàng)建一個(gè)定長的線程池,而且支持定時(shí)的以及周期性的任務(wù)執(zhí)行,類似于Timer。

非核心線程數(shù)沒有限制,并且非核心線程閑置的時(shí)候立即回收,主要用于執(zhí)行定時(shí)任務(wù)和具有固定周期的重復(fù)任務(wù)。

4. Executors.newSingleThreadExecutor()

創(chuàng)建一個(gè)單線程化的executor,它只創(chuàng)建唯一的worker線程來執(zhí)行任務(wù)

只有一個(gè)核心線程,保證所有的任務(wù)都在一個(gè)線程中順序執(zhí)行,意義在于不需要處理線程同步的問題。

一般用于執(zhí)行后臺(tái)耗時(shí)任務(wù),當(dāng)任務(wù)執(zhí)行完成會(huì)自動(dòng)停止;同時(shí)由于它是一個(gè)服務(wù),優(yōu)先級(jí)要遠(yuǎn)遠(yuǎn)高于線程,更不容易被系統(tǒng)殺死,因此比較適合執(zhí)行一些高優(yōu)先級(jí)的后臺(tái)任務(wù)。

使用步驟:創(chuàng)建IntentService的子類,重寫onHandleIntent方法,在onHandleIntent中執(zhí)行耗時(shí)任務(wù)

原理:在源碼實(shí)現(xiàn)上,IntentService封裝了HandlerThread和Handler。onHandleIntent方法結(jié)束后會(huì)調(diào)用IntentService的stopSelf(int startId)方法嘗試停止服務(wù)。

IntentService的內(nèi)部是通過消息的方式請(qǐng)求HandlerThread執(zhí)行任務(wù),HandlerThread內(nèi)部又是一種使用Handler的Thread,這就意味著IntentService和Looper一樣是順序執(zhí)行后臺(tái)任務(wù)的

(HandlerThread:封裝了Handler + ThreadHandlerThread適合在有需要一個(gè)工作線程(非UI線程)+任務(wù)的等待隊(duì)列的形式,優(yōu)點(diǎn)是不會(huì)有堵塞,減少了對(duì)性能的消耗,缺點(diǎn)是不能同時(shí)進(jìn)行多個(gè)任務(wù)的處理,需要等待進(jìn)行處理。處理效率低,可以當(dāng)成一個(gè)輕量級(jí)的線程池來用)

Android線程池ThreadPoolExecutor詳解

傳統(tǒng)的多線程是通過繼承Thread類及實(shí)現(xiàn)Runnable接口來實(shí)現(xiàn)的,每次創(chuàng)建及銷毀線程都會(huì)消耗資源、響應(yīng)速度慢,且線程缺乏統(tǒng)一管理,容易出現(xiàn)阻塞的情況,針對(duì)以上缺點(diǎn),線程池就出現(xiàn)了。

線程池是一個(gè)創(chuàng)建使用線程并能保存使用過的線程以達(dá)到復(fù)用的對(duì)象,簡(jiǎn)單的說就是一塊緩存了一定數(shù)量線程的區(qū)域。

1.復(fù)用線程:線程執(zhí)行完不會(huì)立刻退出,繼續(xù)執(zhí)行其他線程;

2.管理線程:統(tǒng)一分配、管理、控制最大并發(fā)數(shù);

1.降低因頻繁創(chuàng)建銷毀線程帶來的性能開銷,復(fù)用緩存在線程池中的線程;

2.提高線程執(zhí)行效率響應(yīng)速度,復(fù)用線程:響應(yīng)速度;管理線程:優(yōu)化線程執(zhí)行順序,避免大量線程搶占資源導(dǎo)致阻塞現(xiàn)象;

3.提高對(duì)線程的管理度;

線程池的使用也比較簡(jiǎn)單,流程如下:

接下來通過源碼來介紹一下ThreadPoolExecutor內(nèi)部實(shí)現(xiàn)及工作原理。

線程池的最終實(shí)現(xiàn)類是ThreadPoolExecutor,通過實(shí)現(xiàn)可以一步一步的看到,父接口為Executor:

其他的繼承及實(shí)現(xiàn)關(guān)系就不一一列舉了,直接通過以下圖來看一下:

從構(gòu)造方法開始看:

通過以上可以看到,在創(chuàng)建ThreadPoolExecutor時(shí),對(duì)傳入的參數(shù)是有要求的:corePoolSize不能小于0;maximumPoolSize需要大于0,且需要大于等于corePoolSize;keepAliveTime大于0;workQueue、threadFactory都不能為null。

在創(chuàng)建完后就需要執(zhí)行Runnable了,看以下execute()方法:

在execute()內(nèi)部主要執(zhí)行的邏輯如下:

分析點(diǎn)1:如果當(dāng)前線程數(shù)未超過核心線程數(shù),則將runnable作為參數(shù)執(zhí)行addWorker(),true表示核心線程,false表示非核心線程;

分析點(diǎn)2:核心線程滿了,如果線程池處于運(yùn)行狀態(tài)則往workQueue隊(duì)列中添加任務(wù),接下來判斷是否需要拒絕或者執(zhí)行addWorker();

分析點(diǎn)3:以上都不滿足時(shí) [corePoolSize=0且沒有運(yùn)行的線程,或workQueue已經(jīng)滿了] ,執(zhí)行addWorker()添加runnable,失敗則執(zhí)行拒絕策略;

總結(jié)一下:線程池對(duì)線程創(chuàng)建的管理,流程圖如下:

在執(zhí)行addWorker時(shí),主要做了以下兩件事:

分析點(diǎn)1:將runnable作為參數(shù)創(chuàng)建Worker對(duì)象w,然后獲取w內(nèi)部的變量thread;

分析點(diǎn)2:調(diào)用start()來啟動(dòng)thread;

在addWorker()內(nèi)部會(huì)將runnable作為參數(shù)傳給Worker,然后從Worker內(nèi)部讀取變量thread,看一下Worker類的實(shí)現(xiàn):

Worker實(shí)現(xiàn)了Runnable接口,在Worker內(nèi)部,進(jìn)行了賦值及創(chuàng)建操作,先將execute()時(shí)傳入的runnable賦值給內(nèi)部變量firstTask,然后通過ThreadFactory.newThread(this)創(chuàng)建Thread,上面講到在addWorker內(nèi)部執(zhí)行t.start()后,會(huì)執(zhí)行到Worker內(nèi)部的run()方法,接著會(huì)執(zhí)行runWorker(this),一起看一下:

前面可以看到,runWorker是執(zhí)行在子線程內(nèi)部,主要執(zhí)行了三件事:

分析1:獲取當(dāng)前線程,當(dāng)執(zhí)行shutdown()時(shí)需要將線程interrupt(),接下來從Worker內(nèi)部取到firstTask,即execute傳入的runnable,接下來會(huì)執(zhí)行;

分析2:while循環(huán),task不空直接執(zhí)行;否則執(zhí)行g(shù)etTask()去獲取,不為空直接執(zhí)行;

分析3:對(duì)有效的task執(zhí)行run(),由于是在子線程中執(zhí)行,因此直接run()即可,不需要start();

前面看到,在while內(nèi)部有執(zhí)行g(shù)etTask(),一起看一下:

getTask()是從workQueue內(nèi)部獲取接下來需要執(zhí)行的runnable,內(nèi)部主要做了兩件事:

分析1:先獲取到當(dāng)前正在執(zhí)行工作的線程數(shù)量wc,通過判斷allowCoreThreadTimeOut[在創(chuàng)建ThreadPoolExecutor時(shí)可以進(jìn)行設(shè)置]及wc corePoolSize來確定timed值;

分析2:通過timed值來決定執(zhí)行poll()或者take(),如果WorkQueue中有未執(zhí)行的線程時(shí),兩者作用是相同的,立刻返回線程;如果WorkQueue中沒有線程時(shí),poll()有超時(shí)返回,take()會(huì)一直阻塞;如果allowCoreThreadTimeOut為true,則核心線程在超時(shí)時(shí)間沒有使用的話,是需要退出的;wc corePoolSize時(shí),非核心線程在超時(shí)時(shí)間沒有使用的話,是需要退出的;

allowCoreThreadTimeOut是可以通過以下方式進(jìn)行設(shè)置的:

如果沒有進(jìn)行設(shè)置,那么corePoolSize數(shù)量的核心線程會(huì)一直存在。

總結(jié)一下:ThreadPoolExecutor內(nèi)部的核心線程如何確保一直存在,不退出?

上面分析已經(jīng)回答了這個(gè)問題,每個(gè)線程在執(zhí)行時(shí)會(huì)執(zhí)行runWorker(),而在runWorker()內(nèi)部有while()循環(huán)會(huì)判斷getTask(),在getTask()內(nèi)部會(huì)對(duì)當(dāng)前執(zhí)行的線程數(shù)量及allowCoreThreadTimeOut進(jìn)行實(shí)時(shí)判斷,如果工作數(shù)量大于corePoolSize且workQueue中沒有未執(zhí)行的線程時(shí),會(huì)執(zhí)行poll()超時(shí)退出;如果工作數(shù)量不大于corePoolSize且workQueue中沒有未執(zhí)行的線程時(shí),會(huì)執(zhí)行take()進(jìn)行阻塞,確保有corePoolSize數(shù)量的線程阻塞在runWorker()內(nèi)部的while()循環(huán)不退出。

如果需要關(guān)閉線程池,需要如何操作呢,看一下shutdown()方法:

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

也可調(diào)用shutdownNow()來關(guān)閉線程池,二者區(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();

總結(jié)一下:ThreadPoolExecutor在執(zhí)行execute()及shutdown()時(shí)的調(diào)用關(guān)系,流程圖如下:

線程池可以通過Executors來進(jìn)行不同類型的創(chuàng)建,具體分為四種不同的類型,如下:

可緩存線程池:不固定線程數(shù)量,且支持最大為Integer.MAX_VALUE的線程數(shù)量:

1、線程數(shù)無限制

2、有空閑線程則復(fù)用空閑線程,若無空閑線程則新建線程

3、一定程度上減少頻繁創(chuàng)建/銷毀線程,減少系統(tǒng)開銷

固定線程數(shù)量的線程池:定長線程池

1、可控制線程最大并發(fā)數(shù)(同時(shí)執(zhí)行的線程數(shù))

2、超出的線程會(huì)在隊(duì)列中等待。

單線程化的線程池:可以理解為線程數(shù)量為1的FixedThreadPool

1、有且僅有一個(gè)工作線程執(zhí)行任務(wù)

2、所有任務(wù)按照指定順序執(zhí)行,即遵循隊(duì)列的入隊(duì)出隊(duì)規(guī)則

定時(shí)以指定周期循環(huán)執(zhí)行任務(wù)

一般來說,等待隊(duì)列 BlockingQueue 有: ArrayBlockingQueue 、 LinkedBlockingQueue 與 SynchronousQueue 。

假設(shè)向線程池提交任務(wù)時(shí),核心線程都被占用的情況下:

ArrayBlockingQueue :基于數(shù)組的阻塞隊(duì)列,初始化需要指定固定大小。

當(dāng)使用此隊(duì)列時(shí),向線程池提交任務(wù),會(huì)首先加入到等待隊(duì)列中,當(dāng)?shù)却?duì)列滿了之后,再次提交任務(wù),嘗試加入隊(duì)列就會(huì)失敗,這時(shí)就會(huì)檢查如果當(dāng)前線程池中的線程數(shù)未達(dá)到最大線程,則會(huì)新建線程執(zhí)行新提交的任務(wù)。所以最終可能出現(xiàn)后提交的任務(wù)先執(zhí)行,而先提交的任務(wù)一直在等待。

LinkedBlockingQueue :基于鏈表實(shí)現(xiàn)的阻塞隊(duì)列,初始化可以指定大小,也可以不指定。

當(dāng)指定大小后,行為就和 ArrayBlockingQueue一致。而如果未指定大小,則會(huì)使用默認(rèn)的 Integer.MAX_VALUE 作為隊(duì)列大小。這時(shí)候就會(huì)出現(xiàn)線程池的最大線程數(shù)參數(shù)無用,因?yàn)闊o論如何,向線程池提交任務(wù)加入等待隊(duì)列都會(huì)成功。最終意味著所有任務(wù)都是在核心線程執(zhí)行。如果核心線程一直被占,那就一直等待。

SynchronousQueue :無容量的隊(duì)列。

使用此隊(duì)列意味著希望獲得最大并發(fā)量。因?yàn)闊o論如何,向線程池提交任務(wù),往隊(duì)列提交任務(wù)都會(huì)失敗。而失敗后如果沒有空閑的非核心線程,就會(huì)檢查如果當(dāng)前線程池中的線程數(shù)未達(dá)到最大線程,則會(huì)新建線程執(zhí)行新提交的任務(wù)。完全沒有任何等待,唯一制約它的就是最大線程數(shù)的個(gè)數(shù)。因此一般配合Integer.MAX_VALUE就實(shí)現(xiàn)了真正的無等待。

但是需要注意的是, 進(jìn)程的內(nèi)存是存在限制的,而每一個(gè)線程都需要分配一定的內(nèi)存。所以線程并不能無限個(gè)。

Android 線程池的封裝

GlobalThreadPools.java:

調(diào)用:

線程池

線程池概念來源于Java中的Executor,它是一個(gè)接口,真正的實(shí)現(xiàn)為ThreadPoolExecutor。ThreadPoolExecutor提供了一系列參數(shù)來配置線程池。

優(yōu)點(diǎn)

1:重用線程池中的線程,線程在執(zhí)行完任務(wù)后不會(huì)立刻銷毀,而會(huì)等待另外的任務(wù),這樣就不會(huì)頻繁地創(chuàng)建、銷毀線程和調(diào)用GC。。

2:有效控制線程池的最大并發(fā)數(shù),避免大量線程搶占資源出現(xiàn)的問題。

3:對(duì)多個(gè)線程進(jìn)行統(tǒng)一地管理,可提供定時(shí)執(zhí)行及指定間隔循環(huán)執(zhí)行的功能。

ThreadPoolExecutor 有多個(gè)重載方法,但最終都調(diào)用了這個(gè)構(gòu)造方法

public ThreadPoolExecutor(int corePoolSize,

int maximumPoolSize,

long keepAliveTime,

TimeUnit unit,

BlockingQueueRunnable workQueue,

ThreadFactory threadFactory,

RejectedExecutionHandler handler)

參數(shù):

corePoolSize:線程池中核心線程的數(shù)量;為了內(nèi)存優(yōu)化,在線程池維護(hù)了幾個(gè)重要的線程,不達(dá)到一定條件不開辟其余線程

maximumPoolSize :線程池中最大線程數(shù)量:這個(gè)數(shù)量是包括核心線程的,當(dāng)線程池中的正在執(zhí)行的線程池達(dá)到了這個(gè)數(shù)字,再提交線程如果你不做特殊處理將會(huì)拋出異常

keepAliveTime:非核心線程的超時(shí)時(shí)長;當(dāng)線程池中的非核心線程閑置時(shí)間超過這個(gè)值代表的時(shí)間后,將會(huì)被回收;同時(shí)如果調(diào)用ThreadPoolExecutor.allowCoreThreadTimeOut(true),那么核心線程也會(huì)符合這個(gè)設(shè)置

unit:keepAliveTime值的單位,可以是時(shí)分秒等

workQueue:存放待執(zhí)行的線程;你通過execute方法提交線程,但是這些線程還沒達(dá)到執(zhí)行條件,那么就會(huì)保存在這個(gè)隊(duì)列里

threadFactory:創(chuàng)建線程池的工廠;在這個(gè)工廠里,我們可以指定線程的一些信息

handler:線程提交拒絕策略;通常是線程池中的正在執(zhí)行的線程數(shù)量已經(jīng)達(dá)到了最大線程數(shù)或線程池關(guān)閉,如果不傳,默認(rèn)是拋出一個(gè)RejectedExecutionException,所以最好傳下

推薦使用 Executors 的工廠方法來創(chuàng)建線程池,通過直接或間接的配置 ThreadPoolExecutor 的參數(shù)來構(gòu)建線程池,常用的線程池有如下 4 種,newFixedThreadPool ,newCachedThreadPool,

newScheduledThreadPool 和 newSingleThreadExecutor。

ThreadPoolExecutor 執(zhí)行任務(wù)時(shí)大致遵循如下流程:

1.如果線程池中的線程數(shù)未達(dá)到核心線程數(shù),則會(huì)立馬啟用一個(gè)核心線程去執(zhí)行。

2.如果線程池中的線程數(shù)已經(jīng)達(dá)到核心線程數(shù),且任務(wù)隊(duì)列workQueue未滿,則將新線程放入workQueue中等待執(zhí)行。

3.如果線程池中的線程數(shù)已經(jīng)達(dá)到核心線程數(shù)但未超過線程池規(guī)定最大值,且workQueue已滿,則開啟一個(gè)非核心線程來執(zhí)行任務(wù)。

4.如果線程池中的線程數(shù)已經(jīng)超過線程池規(guī)定最大值,則拒絕執(zhí)行該任務(wù),采取飽和策略,并拋出RejectedExecutionException異常。

線程池大小:(N為CPU數(shù)量)

如果是CPU密集型應(yīng)用,則線程池大小設(shè)置為N+1

如果是IO密集型應(yīng)用,則線程池大小設(shè)置為2N+1

I/O密集型

指的是系統(tǒng)的CPU效能相對(duì)硬盤/內(nèi)存的效能要好,大部分的狀況是 CPU 在等 I/O (硬盤/內(nèi)存) 的讀/寫, CPU Loading 不高。

CPU密集型

指的是系統(tǒng)的 硬盤/內(nèi)存 效能 相對(duì) CPU 的效能 要好,大部分的狀況是 CPU Loading 100%,CPU 要讀/寫 I/O (硬盤/內(nèi)存),I/O在很短的時(shí)間就可以完成,而 CPU 還有許多運(yùn)算要處理,CPU Loading 很高。

獲取CPU數(shù)量的方法為:

Runtime.getRuntime().availableProcessors();

摘自:

Android線程池的使用

在Android中有主線程和子線程的區(qū)分。主線程又稱為UI線程,主要是處理一些和界面相關(guān)的事情,而子線程主要是用于處理一些耗時(shí)比較大的一些任務(wù),例如一些網(wǎng)絡(luò)操作,IO請(qǐng)求等。如果在主線程中處理這些耗時(shí)的任務(wù),則有可能會(huì)出現(xiàn)ANR現(xiàn)象(App直接卡死)。

線程池,從名字的表明含義上我們知道線程池就是包含線程的一個(gè)池子,它起到新建線程、管理線程、調(diào)度線程等作用。

既然Android中已經(jīng)有了線程的概念,那么為什么需要使用線程池呢?我們從兩個(gè)方面給出使用線程池的原因。

在Android中線程池就是ThreadPoolExecutor對(duì)象。我們先來看一下ThreadPoolExecutor的構(gòu)造函數(shù)。

我們分別說一下當(dāng)前的幾個(gè)參數(shù)的含義:

第一個(gè)參數(shù)corePoolSize為 核心線程數(shù) ,也就是說線程池中至少有這么多的線程,即使存在的這些線程沒有執(zhí)行任務(wù)。但是有一個(gè)例外就是,如果在線程池中設(shè)置了allowCoreThreadTimeOut為true,那么在 超時(shí)時(shí)間(keepAliveTime) 到達(dá)后核心線程也會(huì)被銷毀。

第二個(gè)參數(shù)maximumPoolSize為 線程池中的最大線程數(shù) 。當(dāng)活動(dòng)線程數(shù)達(dá)到這個(gè)數(shù)后,后續(xù)添加的新任務(wù)會(huì)被阻塞。

第三個(gè)參數(shù)keepAliveTime為 線程的保活時(shí)間 ,就是說如果線程池中有多于核心線程數(shù)的線程,那么在線程沒有任務(wù)的那一刻起開始計(jì)時(shí),如果超過了keepAliveTime,還沒有新的任務(wù)過來,則該線程就要被銷毀。同時(shí)如果設(shè)置了allowCoreThreadTimeOut為true,該時(shí)間也就是上面第一條所說的 超時(shí)時(shí)間 。

第四個(gè)參數(shù)unit為 第三個(gè)參數(shù)的計(jì)時(shí)單位 ,有毫秒、秒等。

第五個(gè)參數(shù)workQueue為 線程池中的任務(wù)隊(duì)列 ,該隊(duì)列持有由execute方法傳遞過來的Runnable對(duì)象(Runnable對(duì)象就是一個(gè)任務(wù))。這個(gè)任務(wù)隊(duì)列的類型是BlockQueue類型,也就是阻塞隊(duì)列,當(dāng)隊(duì)列的任務(wù)數(shù)為0時(shí),取任務(wù)的操作會(huì)被阻塞;當(dāng)隊(duì)列的任務(wù)數(shù)滿了(活動(dòng)線程達(dá)到了最大線程數(shù)),添加操作就會(huì)阻塞。

第六個(gè)參數(shù)threadFactory為 線程工廠 ,當(dāng)線程池需要?jiǎng)?chuàng)建一個(gè)新線程時(shí),使用線程工廠來給線程池提供一個(gè)線程。

第七個(gè)參數(shù)handler為 拒絕策略 ,當(dāng)線程池使用有界隊(duì)列時(shí)(也就是第五個(gè)參數(shù)),如果隊(duì)列滿了,任務(wù)添加到線程池的時(shí)候的一個(gè)拒絕策略。

可以看到FixedThreadPool的構(gòu)建調(diào)用了ThreadPoolExecutor的構(gòu)造函數(shù)。從上面的調(diào)用中可以看出FixedThreadPool的幾個(gè)特點(diǎn):

可以看到CacheThreadPool的構(gòu)建調(diào)用了ThreadPoolExecutor的構(gòu)造函數(shù)。從上面的調(diào)用中可以看出CacheThreadPool的幾個(gè)特點(diǎn):

可以看到ScheduledThreadPoolExecutor的構(gòu)建調(diào)用了ThreadPoolExecutor的構(gòu)造函數(shù)。從上面的調(diào)用中可以看出ScheduledThreadPoolExecutor的幾個(gè)特點(diǎn):

可以看到SingleThreadExecutor的構(gòu)建調(diào)用了ThreadPoolExecutor的構(gòu)造函數(shù)。從上面的調(diào)用中可以看出SingleThreadExecutor的幾個(gè)特點(diǎn):

分享題目:android線程池,Android線程池面試題
當(dāng)前地址:http://www.chinadenli.net/article40/dsdideo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供自適應(yīng)網(wǎng)站網(wǎng)站內(nèi)鏈標(biāo)簽優(yōu)化服務(wù)器托管網(wǎng)頁設(shè)計(jì)公司網(wǎng)站營銷

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)