當前位置:首頁 » 安卓系統 » android使用線程池

android使用線程池

發布時間: 2023-05-31 10:09:05

Ⅰ Android 中的「子線程」解析

Android 中線程可分為 主線程 和 子線程 兩類,其中主線程也就是 UI線程 ,它的主要這作用就是運行四大組件、處理界面交互。子線程則主要是處理耗時任務,也是我們要重點分析的。

首先 java 中的各種線程在 Android 里是通用的,Android 特有的線程形態也是基於 Java 的實現的,所以有必要先簡單的了解下 Java 中的線程,本文主要包括以下內容:

在 Java 中要創建子線程可以直接繼承 Thread 類,重寫 run() 方法:

或者實現 Runnable 介面,然後用Thread執行Runnable,這種方式比較常用:

簡單的總結下:

Callable 和 Runnable 類似,都可以用來處理具體的耗時任務邏輯的,但是但具體的差別在哪裡呢?看一個小例子:

定義 MyCallable 實現了 Callable 介面,和之前 Runnable 的 run() 方法對比下, call() 方法是有返回值的哦,泛型就是返回值的類型:

一般會通過線程池來執行 Callable (線程池相關內容後邊會講到),執行結果就是一個 Future 對象:

可以看到,通過線程池執行 MyCallable 對象返回了一個 Future 對象,取出執行結果。

Future 是一個介面,從其內部的方法可以看出它提供了取消任務(有坑!!!)、判斷任務是否完成、獲取任務結果的功能:

Future 介面有一個 FutureTask 實現類,同時 FutureTask 也實現了 Runnable 介面,並提供了兩個構造函數:

用 FutureTask 一個參數的構造函數來改造下上邊的例子:

FutureTask 內部有一個 done() 方法,代表 Callable 中的任務已經結束,可以用來獲取執行結果:

所以 Future + Callable 的組合可以更方便的獲取子線程任務的執行結果,更好的控制任務的執行,主要的用法先說這么多了,其實 AsyncTask 內部也是類似的實現!

注意, Future 並不能取消掉運行中的任務,這點在後邊的 AsyncTask 解析中有提到。

Java 中線程池的具體的實現類是 ThreadPoolExecutor ,繼承了 Executor 介面,這些線程池在 Android 中也是通用的。使用線程池的好處:

常用的構造函數如下:

一個常規線程池可以按照如下方式來實現:

執行任務:

基於 ThreadPoolExecutor ,系統擴展了幾類具有新特性的線程池:

線程池可以通過 execute() 、 submit() 方法開始執行任務,主要差別從方法的聲明就可以看出,由於 submit() 有返回值,可以方便得到任務的執行結果:

要關閉線程池可以使用如下方法:

IntentService 是 Android 中一種特殊的 Service,可用於執行後台耗時任務,任務結束時會自動停止,由於屬於系統的四大組件之一,相比一般線程具有較高的優先順序,不容易被殺死。用法和普通 Service 基本一致,只需要在 onHandleIntent() 中處理耗時任務即可:

至於 HandlerThread,它是 IntentService 內部實現的重要部分,細節內容會在 IntentService 源碼中說到。

IntentService 首次創建被啟動的時候其生命周期方法 onCreate() 會先被調用,所以我們從這個方法開始分析:

這里出現了 HandlerThread 和 ServiceHandler 兩個類,先搞明白它們的作用,以便後續的分析。

首先看 HandlerThread 的核心實現:

首先它繼承了 Thread 類,可以當做子線程來使用,並在 run() 方法中創建了一個消息循環系統、開啟消息循環。

ServiceHandler 是 IntentService 的內部類,繼承了 Handler,具體內容後續分析:

現在回過頭來看 onCreate() 方法主要是一些初始化的操作, 首先創建了一個 thread 對象,並啟動線程,然後用其內部的 Looper 對象 創建一個 mServiceHandler 對象,將子線程的 Looper 和 ServiceHandler 建立了綁定關系,這樣就可以使用 mServiceHandler 將消息發送到子線程去處理了。

生命周期方法 onStartCommand() 方法會在 IntentService 每次被啟動時調用,一般會這里處理啟動 IntentService 傳遞 Intent 解析攜帶的數據:

又調用了 start() 方法:

就是用 mServiceHandler 發送了一條包含 startId 和 intent 的消息,消息的發送還是在主線程進行的,接下來消息的接收、處理就是在子線程進行的:

當接收到消息時,通過 onHandleIntent() 方法在子線程處理 intent 對象, onHandleIntent() 方法執行結束後,通過 stopSelf(msg.arg1) 等待所有消息處理完畢後終止服務。

為什麼消息的處理是在子線程呢?這里涉及到 Handler 的內部消息機制,簡單的說,因為 ServiceHandler 使用的 Looper 對象就是在 HandlerThread 這個子線程類里創建的,並通過 Looper.loop() 開啟消息循環,不斷從消息隊列(單鏈表)中取出消息,並執行,截取 loop() 的部分源碼:

dispatchMessage() 方法間接會調用 handleMessage() 方法,所以最終 onHandleIntent() 就在子線程中劃線執行了,即 HandlerThread 的 run() 方法。

這就是 IntentService 實現的核心,通過 HandlerThread + Hanlder 把啟動 IntentService 的 Intent 從主線程切換到子線程,實現讓 Service 可以處理耗時任務的功能!

AsyncTask 是 Android 中輕量級的非同步任務抽象類,它的內部主要由線程池以及 Handler 實現,在線程池中執行耗時任務並把結果通過 Handler 機制中轉到主線程以實現UI操作。典型的用法如下:

從 Android3.0 開始,AsyncTask 默認是串列執行的:

如果需要並行執行可以這么做:

AsyncTask 的源碼不多,還是比較容易理解的。根據上邊的用法,可以從 execute() 方法開始我們的分析:

看到 @MainThread 註解了嗎?所以 execute() 方法需要在主線程執行哦!

進而又調用了 executeOnExecutor() :

可以看到,當任務正在執行或者已經完成,如果又被執行會拋出異常!回調方法 onPreExecute() 最先被執行了。

傳入的 sDefaultExecutor 參數,是一個自定義的串列線程池對象,所有任務在該線程池中排隊執行:

可以看到 SerialExecutor 線程池僅用於任務的排隊, THREAD_POOL_EXECUTOR 線程池才是用於執行真正的任務,就是我們線程池部分講到的 ThreadPoolExecutor :

再回到 executeOnExecutor() 方法中,那麼 exec.execute(mFuture) 就是觸發線程池開始執行任務的操作了。

那 executeOnExecutor() 方法中的 mWorker 是什麼? mFuture 是什麼?答案在 AsyncTask 的構造函數中:

原來 mWorker 是一個 Callable 對象, mFuture 是一個 FutureTask 對象,繼承了 Runnable 介面。所以 mWorker 的 call() 方法會在 mFuture 的 run() 方法中執行,所以 mWorker 的 call() 方法在線程池得到執行!

同時 doInBackground() 方法就在 call() 中方法,所以我們自定義的耗時任務邏輯得到執行,不就是我們第二部分講的那一套嗎!

doInBackground() 的返回值會傳遞給 postResult() 方法:

就是通過 Handler 將最終的耗時任務結果從子線程發送到主線程,具體的過程是這樣的, getHandler() 得到的就是 AsyncTask 構造函數中初始化的 mHandler , mHander 又是通過 getMainHandler() 賦值的:

可以在看到 sHandler 是一個 InternalHandler 類對象:

所以 getHandler() 就是在得到在主線程創建的 InternalHandler 對象,所以
就可以完成耗時任務結果從子線程到主線程的切換,進而可以進行相關UI操作了。
當消息是 MESSAGE_POST_RESULT 時,代表任務執行完成, finish() 方法被調用:

如果任務沒有被取消的話執行 onPostExecute() ,否則執行 onCancelled() 。

如果消息是 MESSAGE_POST_PROGRESS , onProgressUpdate() 方法被執行,根據之前的用法可以 onProgressUpdate() 的執行需要我們手動調用 publishProgress() 方法,就是通過 Handler 來發送進度數據:

進行中的任務如何取消呢?AsyncTask 提供了一個 cancel(boolean mayInterruptIfRunning) ,參數代表是否中斷正在執行的線程任務,但是呢並不靠譜, cancel() 的方法注釋中有這么一段:

大致意思就是調用 cancel() 方法後, onCancelled(Object) 回調方法會在 doInBackground() 之後被執行而 onPostExecute() 將不會被執行,同時你應該 doInBackground() 回調方法中通過 isCancelled() 來檢查任務是否已取消,進而去終止任務的執行!

所以只能自己動手了:

AsyncTask 整體的實現流程就這些了,源碼是最好的老師,自己跟著源碼走一遍有些問題可能就豁然開朗了!

Ⅱ android 使用線程池耗性能嗎

當然
耗性能,就碼慶算你不用,遲鎮也會有幾個線碼模粗程在跑。
一般用線程池都是非常頻繁的操作。

Ⅲ Android線程池的使用

在Android中有主線程和子線程的區分。主線程又稱為UI線程,主要是處理一些和界面相關的事情,而子線程主要是用於處理一些耗時比較大的一些任務,例如一些網路操作,IO請求等。如果在主線程中處理這些耗時的任務,則有可能會出現ANR現象(App直接卡死)。

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

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

在Android中線程池就是ThreadPoolExecutor對象。我們先來看一下ThreadPoolExecutor的構造函數。

我們分別說一下當前的幾個參數的含義:
第一個參數corePoolSize為 核心線程數 ,也就是說線程池中至少有這么多的線程,即使存在的這些線程沒有執行任務。但是有一個例外就是,如果在線程池中設置了allowCoreThreadTimeOut為true,那麼在 超時時間(keepAliveTime) 到達後核心線程也會被銷毀。
第二個參數maximumPoolSize為 線程池中的最大線程數 。當活動線程數達到這個數後,後續添加的新任務會被阻塞。
第三個參數keepAliveTime為 線程的保活時間 ,就是說如果線程池中有多於核心線程數的線程,那麼在線程沒有任務的那一刻起開始計時,如果超過了keepAliveTime,還沒有新的任務過來,則該線程就要被銷毀。同時如果設置了allowCoreThreadTimeOut為true,該時間也就是上面第一條所說的 超時時間
第四個參數unit為 第三個參數的計時單位 ,有毫秒、秒等。
第五個參數workQueue為 線程池中的任務隊列 ,該隊列持有由execute方法傳遞過來的Runnable對象(Runnable對象就是一個任務)。這個任務隊列的類型是BlockQueue類型,也就是阻塞隊列,當隊列的任務數為0時,取任務的操作會被阻塞;當隊列的任務數滿了(活動線程達到了最大線程數),添加操作就會阻塞。
第六個參數threadFactory為 線程工廠 ,當線程池需要創建一個新線程時,使用線程工廠來給線程池提供一個線程。
第七個參數handler為 拒絕策略 ,當線程池使用有界隊列時(也就是第五個參數),如果隊列滿了,任務添加到線程池的時候的一個拒絕策略。

可以看到FixedThreadPool的構建調用了ThreadPoolExecutor的構造函數。從上面的調用中可以看出FixedThreadPool的幾個特點:

可以看到CacheThreadPool的構建調用了ThreadPoolExecutor的構造函數。從上面的調用中可以看出CacheThreadPool的幾個特點:

可以看到ScheledThreadPoolExecutor的構建調用了ThreadPoolExecutor的構造函數。從上面的調用中可以看出ScheledThreadPoolExecutor的幾個特點:

可以看到SingleThreadExecutor的構建調用了ThreadPoolExecutor的構造函數。從上面的調用中可以看出SingleThreadExecutor的幾個特點:

Ⅳ Android中的線程和線程池

一、除了Thread外,扮演線程角色的還有:AsyncTask和IntentService,同時HandlerThread也扮演特殊的線程。

      IntentService:內部採用HandlerThread來執行,像一個後台線程,同時是一個服務,不容易被系統殺死。

二、HandlerThread的run方法是一個無限循環

三、IntentService中任務是排隊執行的

四、AsyncTask 

1、Android1.6之前串悄段桐行執行任務,1.6時候採用線程池裡的並行,Android3.0開始又開始串列(為了避免並發錯誤),單任可以並行。

2、AsyncTask必須在UI線程調用(不過這個不是絕對的,和版本有關燃腔系,API 16之前,API 16到 22, API 22以後) 參考一

原因:內部有靜態Handler,採用UI線程的Looper來處理消息,這就是為什麼AsyncTask必須在UI線程調用,因為子線程默認沒有Looper無法創建下面的Handler,程序會直接Crash

3、AsyncTask中有兩個線程池和一個Handler,一個線程池用啟坦於任務排隊,一個線程池用於真正的執行任務,InternalHandler用於將

執行環境從線程池切換到主線程

AsyncTask串列與並行

五、線程池

線程池中多餘的線程是如何回收的

Ⅳ android 線程池 怎麼用

我覺得使用線程池最大的優點是我們可以對我們開啟的線程進行跟進,當我們不需要處理的時候可以將它shutdow掉,同時當我們定義了一個線程池之後,可以復用線程而不需要開啟更多線程,這點對於我們手機開發是至關重要的,你開啟的thread越多意味著你的app內存消耗越多,速度也就越來越慢,提高現有線程的復用是一個很棒的選擇

線程池中處理線程的類別較多如:

限制按順序來執行任務的線程池、一個一個任務的執行線程池、按指定個數來執行任務的線程池、創建一個可在指定時間里執行任務的線程池,亦可重復執行、按指定工廠模式來執行的線程池

Ⅵ Android中的線程狀態 - AsyncTask詳解

在操作系統中,線程是操作系統調度的最小單元,同時線程又是一種受限的系統資源,即線程不可能無限制地產生,並且 線程的創建和銷毀都會有相應的開銷。 當系統中存在大量的線程時,系統會通過會時間片輪轉的方式調度每個線程,因此線程不可能做到絕對的並行。

如果在一個進程中頻繁地創建和銷毀線程,顯然不是高效的做法。正確的做法是採用線程池,一個線程池中會緩存一定數量的線程,通過線程池就可以避免因為頻繁創建和銷毀線程所帶來的系統開銷。

AsyncTask是一個抽象類,它是由Android封裝的一個輕量級非同步類(輕量體現在使用方便、代碼簡潔),它可以在線程池中執行後台任務,然後把執行的進度和最終結果傳遞給主線程並在主線程中更新UI。

AsyncTask的內部封裝了 兩個線程池 (SerialExecutor和THREAD_POOL_EXECUTOR)和 一個Handler (InternalHandler)。

其中 SerialExecutor線程池用於任務的排隊,讓需要執行的多個耗時任務,按順序排列 THREAD_POOL_EXECUTOR線程池才真正地執行任務 InternalHandler用於從工作線程切換到主線程

1.AsyncTask的泛型參數

AsyncTask是一個抽象泛型類。

其中,三個泛型類型參數的含義如下:

Params: 開始非同步任務執行時傳入的參數類型;

Progress: 非同步任務執行過程中,返回下載進度值的類型;

Result: 非同步任務執行完成後,返回的結果類型;

如果AsyncTask確定不需要傳遞具體參數,那麼這三個泛型參數可以用Void來代替。

有了這三個參數類型之後,也就控制了這個AsyncTask子類各個階段的返回類型,如果有不同業務,我們就需要再另寫一個AsyncTask的子類進行處理。

2.AsyncTask的核心方法

onPreExecute()

這個方法會在 後台任務開始執行之間調用,在主線程執行。 用於進行一些界面上的初始化操作,比如顯示一個進度條對話框等。

doInBackground(Params...)

這個方法中的所有代碼都會 在子線程中運行,我們應該在這里去處理所有的耗時任務。

任務一旦完成就可以通過return語句來將任務的執行結果進行返回,如果AsyncTask的第三個泛型參數指定的是Void,就可以不返回任務執行結果。 注意,在這個方法中是不可以進行UI操作的,如果需要更新UI元素,比如說反饋當前任務的執行進度,可以調用publishProgress(Progress...)方法來完成。

onProgressUpdate(Progress...)

當在後台任務中調用了publishProgress(Progress...)方法後,這個方法就很快會被調用,方法中攜帶的參數就是在後台任務中傳遞過來的。 在這個方法中可以對UI進行操作,在主線程中進行,利用參數中的數值就可以對界面元素進行相應的更新。

onPostExecute(Result)

當doInBackground(Params...)執行完畢並通過return語句進行返回時,這個方法就很快會被調用。返回的數據會作為參數傳遞到此方法中, 可以利用返回的數據來進行一些UI操作,在主線程中進行,比如說提醒任務執行的結果,以及關閉掉進度條對話框等。

上面幾個方法的調用順序:

onPreExecute() --> doInBackground() --> publishProgress() --> onProgressUpdate() --> onPostExecute()

如果不需要執行更新進度則為onPreExecute() --> doInBackground() --> onPostExecute(),

除了上面四個方法,AsyncTask還提供了onCancelled()方法, 它同樣在主線程中執行,當非同步任務取消時,onCancelled()會被調用,這個時候onPostExecute()則不會被調用 ,但是要注意的是, AsyncTask中的cancel()方法並不是真正去取消任務,只是設置這個任務為取消狀態,我們需要在doInBackground()判斷終止任務。就好比想要終止一個線程,調用interrupt()方法,只是進行標記為中斷,需要在線程內部進行標記判斷然後中斷線程。

3.AsyncTask的簡單使用

這里我們模擬了一個下載任務,在doInBackground()方法中去執行具體的下載邏輯,在onProgressUpdate()方法中顯示當前的下載進度,在onPostExecute()方法中來提示任務的執行結果。如果想要啟動這個任務,只需要簡單地調用以下代碼即可:

4.使用AsyncTask的注意事項

①非同步任務的實例必須在UI線程中創建,即AsyncTask對象必須在UI線程中創建。

②execute(Params... params)方法必須在UI線程中調用。

③不要手動調用onPreExecute(),doInBackground(Params... params),onProgressUpdate(Progress... values),onPostExecute(Result result)這幾個方法。

④不能在doInBackground(Params... params)中更改UI組件的信息。

⑤一個任務實例只能執行一次,如果執行第二次將會拋出異常。

先從初始化一個AsyncTask時,調用的構造函數開始分析。

這段代碼雖然看起來有點長,但實際上並沒有任何具體的邏輯會得到執行,只是初始化了兩個變數,mWorker和mFuture,並在初始化mFuture的時候將mWorker作為參數傳入。mWorker是一個Callable對象,mFuture是一個FutureTask對象,這兩個變數會暫時保存在內存中,稍後才會用到它們。 FutureTask實現了Runnable介面,關於這部分內容可以看這篇文章。

mWorker中的call()方法執行了耗時操作,即result = doInBackground(mParams);,然後把執行得到的結果通過postResult(result);,傳遞給內部的Handler跳轉到主線程中。在這里這是實例化了兩個變數,並沒有開啟執行任務。

那麼mFuture對象是怎麼載入到線程池中,進行執行的呢?

接著如果想要啟動某一個任務,就需要調用該任務的execute()方法,因此現在我們來看一看execute()方法的源碼,如下所示:

調用了executeOnExecutor()方法,具體執行邏輯在這個方法裡面:

可以 看出,先執行了onPreExecute()方法,然後具體執行耗時任務是在exec.execute(mFuture),把構造函數中實例化的mFuture傳遞進去了。

exec具體是什麼?

從上面可以看出具體是sDefaultExecutor,再追溯看到是SerialExecutor類,具體源碼如下:

終於追溯到了調用了SerialExecutor 類的execute方法。SerialExecutor 是個靜態內部類,是所有實例化的AsyncTask對象公有的,SerialExecutor 內部維持了一個隊列,通過鎖使得該隊列保證AsyncTask中的任務是串列執行的,即多個任務需要一個個加到該隊列中,然後執行完隊列頭部的再執行下一個,以此類推。

在這個方法中,有兩個主要步驟。

①向隊列中加入一個新的任務,即之前實例化後的mFuture對象。

②調用 scheleNext()方法,調用THREAD_POOL_EXECUTOR執行隊列頭部的任務。

由此可見SerialExecutor 類僅僅為了保持任務執行是串列的,實際執行交給了THREAD_POOL_EXECUTOR。

THREAD_POOL_EXECUTOR又是什麼?

實際是個線程池,開啟了一定數量的核心線程和工作線程。然後調用線程池的execute()方法。執行具體的耗時任務,即開頭構造函數中mWorker中call()方法的內容。先執行完doInBackground()方法,又執行postResult()方法,下面看該方法的具體內容:

該方法向Handler對象發送了一個消息,下面具體看AsyncTask中實例化的Hanlder對象的源碼:

在InternalHandler 中,如果收到的消息是MESSAGE_POST_RESULT,即執行完了doInBackground()方法並傳遞結果,那麼就調用finish()方法。

如果任務已經取消了,回調onCancelled()方法,否則回調 onPostExecute()方法。

如果收到的消息是MESSAGE_POST_PROGRESS,回調onProgressUpdate()方法,更新進度。

InternalHandler是一個靜態類,為了能夠將執行環境切換到主線程,因此這個類必須在主線程中進行載入。所以變相要求AsyncTask的類必須在主線程中進行載入。

到此為止,從任務執行的開始到結束都從源碼分析完了。

AsyncTask的串列和並行

從上述源碼分析中分析得到,默認情況下AsyncTask的執行效果是串列的,因為有了SerialExecutor類來維持保證隊列的串列。如果想使用並行執行任務,那麼可以直接跳過SerialExecutor類,使用executeOnExecutor()來執行任務。

四、AsyncTask使用不當的後果

1.)生命周期

AsyncTask不與任何組件綁定生命周期,所以在Activity/或者Fragment中創建執行AsyncTask時,最好在Activity/Fragment的onDestory()調用 cancel(boolean);

2.)內存泄漏

3.) 結果丟失

屏幕旋轉或Activity在後台被系統殺掉等情況會導致Activity的重新創建,之前運行的AsyncTask(非靜態的內部類)會持有一個之前Activity的引用,這個引用已經無效,這時調用onPostExecute()再去更新界面將不再生效。

自己是從事了七年開發的Android工程師,不少人私下問我,2019年Android進階該怎麼學,方法有沒有?

沒錯,年初我花了一個多月的時間整理出來的學習資料,希望能幫助那些想進階提升Android開發,卻又不知道怎麼進階學習的朋友。【 包括高級UI、性能優化、架構師課程、NDK、Kotlin、混合式開發(ReactNative+Weex)、Flutter等架構技術資料 】,希望能幫助到您面試前的復習且找到一個好的工作,也節省大家在網上搜索資料的時間來學習。

Ⅶ android中的線程池 怎麼用

//在Android中實現線程池,首先需要陸搜實現一個線程工廠(ThreadFactory)的子類,具體實現方式如下所示(PriorityThreadFactory.Java):
import android.os.Process;
/**
* A thread factory that create threads with a given thread priority
* @author jony
* @version 1.0
*/
public class PriorityThreadFactory implements ThreadFactory{
private final String mName;
private final int mPriority;
private final AtomicInteger mNumber = new AtomicInteger();

public PriorityThreadFactory(String name, int priority) {
mName = name;//鬧慶 線程池的名稱
mPriority = priority;//線程池的優先順序
}
@Override
public Thread newThread(Runnable r) {
return new Thread(r, mName +"-"+mNumber.getAndIncrement()){
@Override
public void run() {
// 設置線程的優先順序
Process.setThreadPriority(mPriority);
super.run();
}
};
}
}
//以上是創建線程池的一個工具類,接下來為大家介紹本篇文章的重點,線程池的實現方式,具體實現方式如下所示(MyThreadPool.java):
package com.tcl.actionbar;

import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
package com.tcl.actionbar;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ThreadFactory;

// 線程液悉握池的實現方式
public class MyThreadPool {
private final static int POOL_SIZE = 4;// 線程池的大小最好設置成為CUP核數的2N
private final static int MAX_POOL_SIZE = 6;// 設置線程池的最大線程數
private final static int KEEP_ALIVE_TIME = 4;// 設置線程的存活時間
private final Executor mExecutor;
public MyThreadPool() {
// 創建線程池工廠
ThreadFactory factory = new PriorityThreadFactory("thread-pool", android.os.Process.THREAD_PRIORITY_BACKGROUND);
// 創建工作隊列
BlockingQueue workQueue = new LinkedBlockingDeque();
mExecutor = new ThreadPoolExecutor(POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS, workQueue, factory);
}
// 在線程池中執行線程
public void submit(Runnable command){
mExecutor.execute(command);
}
}
//自己覺得這個·代碼不錯,我就只是將它搬了過來,實際代碼地址:http://blog.csdn.net/weihan1314/article/details/7983725

Ⅷ Android中的線程池

 線程池的好處

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

2、能有效控制線程池的最大並發數,避免大量線程因搶占資源而導致的阻塞

3、能對線程進行簡單的管理,提供定時或者指定間隔時間、循環執行等操作

線程池的概率來自於java的Executor介面,實現類是ThreadPoolExecutor, 它提供一系列的參數來配置線程池,以此構建不同的線程池。Android的線程池分4類,都是通過Executors所提供的工廠方法來得到。

ThreadPoolExecutor有四個構造函數,下面這個是最常用的

public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnnable> workQueue, ThreadFactory threadFactory)

corePoolSize

線程池中的核心線程數,默認情況下核心線程會在線程池中一直存活,即使他們處於閑置狀態。如果設置ThreadPoolExecutor 中的allowCoreThreadTimeOut = true, 核心線程在等待新任務到來時有超時機制,時間超過keepAliveTime所指定的時間後,核心線程會終止。

maximumPoolSize

最大線程數

keepAliveTime

非核心線程閑置的超時時間,超過這個時間,非核心線程會被回收。核心線程則要看allowCoreThreadTimeOut屬性的值。

unit

時間單位

workQueue

線程池中的工作隊列

threadFactory

線程工廠,為線程池提供創建新線程的功能。

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

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

1、FixedThreadPool

通過Executors的newFixedThreadPool()創建,這是一個線程數量固定的線程池,裡面所有的線程都是核心線程。

public static ExecutorService newFixedThreadPool(int nThreads){

return new ThreadPoolExecutor(nThreads, nThreads, 0, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())

}

2、CachedThreadPool

通過Executors的newCacheThreadPool()創建,這是一個線程數量不定的線程池,裡面所有的線程都是非核心線程。最大線程數是無限大,當線程池中的線程都處於活動狀態時,新的task會創建新的線程來處理,否則就使用空閑的線程處理,所有的線程都是60s的超時時間,超時後會自動回收。

public static ExecutorService newFixedThreadPool(){

return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>())

}

3、ScheledThreadPool

通過Executors的newScheledThreadPool()創建, 核心線程固定,非核心線程無限大,當非核心線程空閑時,會立即被回收。適合做定時任務或者固定周期的重復任務。

public static ExecutorService newScheledThreadPool(int corePoolSize){

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

}

4、SingleThreadExcecutor

通過Executors的newSingleThreadPool()創建,內部只有一個核心線程。

public static ExecutorService newFixedThreadPool(){

return new ThreadPoolExecutor(1, 1, 0, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())

}

課外知識:LinkedBlockingQueue

LinkedBlockingQueue是由鏈表組成的阻塞隊列,內部head 指向隊列第一個元素,last指向最後一個元素。入隊和出隊都會加鎖阻塞,都是使用了不同的鎖。

DelayedWorkQueue

延時隊列,隊內元素必須是Delayed的實現類。對內元素會按照Delayed時間進行排序,對內元素只有在delayed時間過期了才能出隊。

入隊的時候不阻塞隊列,出隊的時候,如果隊列為空或者隊列里所有元素都等待時間都沒有到期,則該線程進入阻塞狀態。

Ⅸ Android的App中線程池的使用,具體使用多少個線程池


這個需要根據實際情況來確定的,一般來說根據模塊的功能和優先順序來區分,比如你一些必須載入的如用鄭冊戶登錄就不要和圖片加喊差宏載的用同一個線程池,當然這種情況比較少見,用慶雹戶和伺服器配置數據的應該單獨用一個線程池,下載模塊應該獨立一個,其它數據展示的用一個,曾經就出現過APP啟動的時候請求的線程過多導致用戶登錄線程一直排不上超時的情況

熱點內容
存儲過程性能優化 發布:2025-02-09 13:42:59 瀏覽:727
源碼失竊 發布:2025-02-09 13:38:34 瀏覽:525
自動瀏覽器腳本 發布:2025-02-09 13:37:00 瀏覽:139
易語言問道源碼 發布:2025-02-09 12:59:03 瀏覽:661
ip和伺服器有關嗎 發布:2025-02-09 12:51:26 瀏覽:950
極光免費腳本 發布:2025-02-09 12:50:33 瀏覽:394
c存儲過程返回結果集 發布:2025-02-09 12:42:00 瀏覽:150
gs哪個配置性價比高 發布:2025-02-09 12:35:57 瀏覽:283
java棧數組 發布:2025-02-09 12:33:37 瀏覽:557
php上傳文件form 發布:2025-02-09 12:33:31 瀏覽:157