真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

android子線程,Android子線程執(zhí)行數(shù)據(jù)庫操作

android創(chuàng)建子線程

你是要怎么個意思?

創(chuàng)新互聯(lián)公司致力于成都網(wǎng)站建設(shè)、成都網(wǎng)站設(shè)計,成都網(wǎng)站設(shè)計,集團網(wǎng)站建設(shè)等服務(wù)標(biāo)準(zhǔn)化,推過標(biāo)準(zhǔn)化降低中小企業(yè)的建站的成本,并持續(xù)提升建站的定制化服務(wù)水平進行質(zhì)量交付,讓企業(yè)網(wǎng)站從市場競爭中脫穎而出。 選擇創(chuàng)新互聯(lián)公司,就選擇了安全、穩(wěn)定、美觀的網(wǎng)站建設(shè)服務(wù)!

創(chuàng)建子線程即就是在你的程序體(也就是MainThread)中創(chuàng)建子線程:

1、匿名內(nèi)部類對Thread類進行覆寫:new

Thread(){

覆寫run方法

}.start();

2、或者

new

Thread(new

Runnable(){········}).start();套用兩層匿名內(nèi)部類也可以

3、再或者就是將當(dāng)前類繼承Runnable然后在當(dāng)前類里覆寫上run方法,最后在需要開線程的地方寫上new

Thread(this).start();

####別忘了在更新UI的時候跳回主線程就行了,用runOnUiThread

和handle機制都可以####

android里的子線程什么時候執(zhí)行

1 AsyncTask(或者Thread)+Handler

啟動子線程,子線程執(zhí)行完任務(wù)后,通過Handler給主線程中的Looper發(fā)送消息

2 Activity.runOnUiThread(Runnable r)

在Activity中啟動子線程,子線程執(zhí)行完成任務(wù)后,調(diào)用runOnUiThread(Runnable r)。runOnUiThread(Runnable r)是Activity中的方法,方法里會判斷當(dāng)前線程是否是UI線程,如果是,run()方法在UI線程執(zhí)行,如果不是,通過mHandler把Runnable發(fā)送到主線程的Looper中,Looper取出消息再分發(fā)給mHandler,mHandler收到消息后,回調(diào)run()方法。mHandler是Activity中一個final修飾的成員,所有的Activity對象共用這一個handler對象。

Android 中的“子線程”解析

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

首先 Java 中的各種線程在 Android 里是通用的,Android 特有的線程形態(tài)也是基于 Java 的實現(xiàn)的,所以有必要先簡單的了解下 Java 中的線程,本文主要包括以下內(nèi)容:

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

或者實現(xiàn) Runnable 接口,然后用Thread執(zhí)行Runnable,這種方式比較常用:

簡單的總結(jié)下:

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

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

一般會通過線程池來執(zhí)行 Callable (線程池相關(guān)內(nèi)容后邊會講到),執(zhí)行結(jié)果就是一個 Future 對象:

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

Future 是一個接口,從其內(nèi)部的方法可以看出它提供了取消任務(wù)(有坑!?。。?、判斷任務(wù)是否完成、獲取任務(wù)結(jié)果的功能:

Future 接口有一個 FutureTask 實現(xiàn)類,同時 FutureTask 也實現(xiàn)了 Runnable 接口,并提供了兩個構(gòu)造函數(shù):

用 FutureTask 一個參數(shù)的構(gòu)造函數(shù)來改造下上邊的例子:

FutureTask 內(nèi)部有一個 done() 方法,代表 Callable 中的任務(wù)已經(jīng)結(jié)束,可以用來獲取執(zhí)行結(jié)果:

所以 Future + Callable 的組合可以更方便的獲取子線程任務(wù)的執(zhí)行結(jié)果,更好的控制任務(wù)的執(zhí)行,主要的用法先說這么多了,其實 AsyncTask 內(nèi)部也是類似的實現(xiàn)!

注意, Future 并不能取消掉運行中的任務(wù),這點在后邊的 AsyncTask 解析中有提到。

Java 中線程池的具體的實現(xiàn)類是 ThreadPoolExecutor ,繼承了 Executor 接口,這些線程池在 Android 中也是通用的。使用線程池的好處:

常用的構(gòu)造函數(shù)如下:

一個常規(guī)線程池可以按照如下方式來實現(xiàn):

執(zhí)行任務(wù):

基于 ThreadPoolExecutor ,系統(tǒng)擴展了幾類具有新特性的線程池:

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

要關(guān)閉線程池可以使用如下方法:

IntentService 是 Android 中一種特殊的 Service,可用于執(zhí)行后臺耗時任務(wù),任務(wù)結(jié)束時會自動停止,由于屬于系統(tǒng)的四大組件之一,相比一般線程具有較高的優(yōu)先級,不容易被殺死。用法和普通 Service 基本一致,只需要在 onHandleIntent() 中處理耗時任務(wù)即可:

至于 HandlerThread,它是 IntentService 內(nèi)部實現(xiàn)的重要部分,細節(jié)內(nèi)容會在 IntentService 源碼中說到。

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

這里出現(xiàn)了 HandlerThread 和 ServiceHandler 兩個類,先搞明白它們的作用,以便后續(xù)的分析。

首先看 HandlerThread 的核心實現(xiàn):

首先它繼承了 Thread 類,可以當(dāng)做子線程來使用,并在 run() 方法中創(chuàng)建了一個消息循環(huán)系統(tǒng)、開啟消息循環(huán)。

ServiceHandler 是 IntentService 的內(nèi)部類,繼承了 Handler,具體內(nèi)容后續(xù)分析:

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

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

又調(diào)用了 start() 方法:

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

當(dāng)接收到消息時,通過 onHandleIntent() 方法在子線程處理 intent 對象, onHandleIntent() 方法執(zhí)行結(jié)束后,通過 stopSelf(msg.arg1) 等待所有消息處理完畢后終止服務(wù)。

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

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

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

AsyncTask 是 Android 中輕量級的異步任務(wù)抽象類,它的內(nèi)部主要由線程池以及 Handler 實現(xiàn),在線程池中執(zhí)行耗時任務(wù)并把結(jié)果通過 Handler 機制中轉(zhuǎn)到主線程以實現(xiàn)UI操作。典型的用法如下:

從 Android3.0 開始,AsyncTask 默認(rèn)是串行執(zhí)行的:

如果需要并行執(zhí)行可以這么做:

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

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

進而又調(diào)用了 executeOnExecutor() :

可以看到,當(dāng)任務(wù)正在執(zhí)行或者已經(jīng)完成,如果又被執(zhí)行會拋出異常!回調(diào)方法 onPreExecute() 最先被執(zhí)行了。

傳入的 sDefaultExecutor 參數(shù),是一個自定義的串行線程池對象,所有任務(wù)在該線程池中排隊執(zhí)行:

可以看到 SerialExecutor 線程池僅用于任務(wù)的排隊, THREAD_POOL_EXECUTOR 線程池才是用于執(zhí)行真正的任務(wù),就是我們線程池部分講到的 ThreadPoolExecutor :

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

那 executeOnExecutor() 方法中的 mWorker 是什么? mFuture 是什么?答案在 AsyncTask 的構(gòu)造函數(shù)中:

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

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

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

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

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

所以 getHandler() 就是在得到在主線程創(chuàng)建的 InternalHandler 對象,所以

就可以完成耗時任務(wù)結(jié)果從子線程到主線程的切換,進而可以進行相關(guān)UI操作了。

當(dāng)消息是 MESSAGE_POST_RESULT 時,代表任務(wù)執(zhí)行完成, finish() 方法被調(diào)用:

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

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

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

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

所以只能自己動手了:

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

Android中的特殊線程——HandlerThread

一般我們想要執(zhí)行耗時操作都會想開啟Thread子線程去處理,但是多次創(chuàng)建和銷毀線程是很耗系統(tǒng)資源的。為了解決這一問題,我們可以自己構(gòu)建一個循環(huán)線程,在線程當(dāng)中創(chuàng)建一個Looper輪循器,來進行消息的輪循, 當(dāng)有耗時任務(wù)需要投放到該循環(huán)線程時,線程就會執(zhí)行耗時任務(wù),任務(wù)執(zhí)行完成之后,線程又會處于阻塞等待狀態(tài),不會馬上銷毀掉,直到下一個耗時任務(wù)被投放進來;即通過阻塞和等待來保證性能最優(yōu),為此Google為我們封裝好了HandlerThread框架。

HandlerThread本質(zhì)上就是一個Thread子線程,不同的是在Thread內(nèi)部有一個Looper開啟了輪循器;

HandlerThread = Handler + Thread + Looper

由于一般的Thread沒有開啟Looper輪循器,所以不能在子線程中創(chuàng)建handler,因為沒有對應(yīng)的MessageQueue與handler相關(guān)聯(lián),而MessageQueue是由Looper進行維護的;如果想在子線程中創(chuàng)建handler,必須先通過Looper.prepare()創(chuàng)建一個Looper,再通過Looper.loop()開啟循環(huán),才能使用Handler。

1、HandlerThread本質(zhì)上是一個線程類,繼承了Thread;

2、HandlerThread有自己的內(nèi)部Looper對象,可以進行l(wèi)oop循環(huán);所以在HandlerThread中可以創(chuàng)建handler來發(fā)送和處理消息;

3、通過獲取HandlerThread的Looper對象傳遞給Handler,可以在handleMessage()中執(zhí)行異步操作;

4、handler中的looper默認(rèn)綁定了UI線程的MessageQueue,對于非UI線程想使用MessageQueue機制的,HandlerThread的內(nèi)部Looper最適合,它不會干擾和阻塞UI線程,減少了對性能的消耗,但是處理效率低;

5、HandlerThread是一個串行隊列,會比較穩(wěn)定;

Android線程池的使用

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


分享文章:android子線程,Android子線程執(zhí)行數(shù)據(jù)庫操作
新聞來源:http://weahome.cn/article/hogcji.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部