(1)創(chuàng)建HandlerThread實例,參數(shù)字符串定義新線程的名稱。

創(chuàng)新互聯(lián)成立于2013年,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項目成都網(wǎng)站建設(shè)、網(wǎng)站建設(shè)網(wǎng)站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元合浦做網(wǎng)站,已為上家服務(wù),為合浦各地企業(yè)和個人服務(wù),聯(lián)系電話:028-86922220
(2)啟動HandlerThread線程。
(3)創(chuàng)建Handler對象,將HandlerThread的Lopper作為參數(shù),這樣就完成了Handler對象與HandlerThread的Looper對象的綁定(這里的Handler對象可以看作是綁定在HandlerThread子線程中,所以handlerMessage里的操作是在子線程中運行的)。 重寫handleMessage處理耗時操作。
這樣我們就可以使用mCheckMsgHandler對象以處理消息的形式來進行耗時操作,完成以后就可以切換到主線程的handler中來更新UI。
依據(jù)剛才的步驟,來實現(xiàn)一個每秒更新數(shù)據(jù)的一個功能,這個功能可以用來更新股票、商品價格等。
進程是系統(tǒng)調(diào)度和資源分配的一個獨立單位。
在Android中,一個應(yīng)用程序就是一個獨立的集成,應(yīng)用運行在一個獨立的環(huán)境中,可以避免其他應(yīng)用程序/進程的干擾。當(dāng)我們啟動一個應(yīng)用程序時,系統(tǒng)就會創(chuàng)建一個進程(該進程是從Zygote中fork出來的,有獨立的ID),接著為這個進程創(chuàng)建一個主線程,然后就可以運行MainActivity了,應(yīng)用程序的組件默認都是運行在其進程中。開發(fā)者可以通過設(shè)置應(yīng)用的組件的運行進程,在清單文件中給組件設(shè)置:android:process = "進程名";可以達到讓組件運行在不同進程中的目的。讓組件運行在不同的進程中,既有好處,也有壞處。我們依次的說明下。
好處:每一個應(yīng)用程序(也就是每一個進程)都會有一個內(nèi)存預(yù)算,所有運行在這個進程中的程序使用的總內(nèi)存不能超過這個值,讓組件運行不同的進程中,可以讓主進程可以擁有更多的空間資源。當(dāng)我們的應(yīng)用程序比較大,需要的內(nèi)存資源比較多時(也就是用戶會抱怨應(yīng)用經(jīng)常出現(xiàn)OutOfMemory時),可以考慮使用多進程。
壞處:每個進程都會有自己的虛擬機實例,因此讓在進程間共享一些數(shù)據(jù)變得相對困難,需要采用進程間的通信來實現(xiàn)數(shù)據(jù)的共享。
線程是進程的一個實體,是CPU調(diào)度和分派的基本單位,它是比進程更小的能獨立運行的基本單位。
在Android中,線程會有那么幾種狀態(tài):創(chuàng)建、就緒、運行、阻塞、結(jié)束。當(dāng)應(yīng)用程序有組件在運行時,UI線程是處于運行狀態(tài)的。默認情況下,應(yīng)用的所有組件的操作都是在UI線程里完成的,包括響應(yīng)用戶的操作(觸摸,點擊等),組件生命周期方法的調(diào)用,UI的更新等。因此如果UI線程處理阻塞狀態(tài)時(在線程里做一些耗時的操作,如網(wǎng)絡(luò)連接等),就會不能響應(yīng)各種操作,如果阻塞時間達到5秒,就會讓程序處于ANR(application not response)狀態(tài)。
1.線程作用
減少程序在并發(fā)執(zhí)行時所付出的時空開銷,提高操作系統(tǒng)的并發(fā)性能。
2.線程分類
守護線程、非守護線程(用戶線程)
2.1 守護線程
定義:守護用戶線程的線程,即在程序運行時為其他線程提供一種通用服務(wù)
常見:如垃圾回收線程
設(shè)置方式:thread.setDaemon(true);//設(shè)置該線程為守護線程
2.2 非守護線程(用戶線程)
主線程 子線程。
2.2.1 主線程(UI線程)
定義:Android系統(tǒng)在程序啟動時會自動啟動一條主線程
作用:處理四大組件與用戶進行交互的事情(如UI、界面交互相關(guān))
因為用戶隨時會與界面發(fā)生交互,因此主線程任何時候都必須保持很高的響應(yīng)速度,所以主線程不允許進行耗時操作,否則會出現(xiàn)ANR。
2.2.2 子線程(工作線程)
定義:手動創(chuàng)建的線程
作用:耗時的操作(網(wǎng)絡(luò)請求、I/O操作等)
2.3 守護線程與非守護線程的區(qū)別和聯(lián)系
區(qū)別:虛擬機是否已退出,即
a. 當(dāng)所有用戶線程結(jié)束時,因為沒有守護的必要,所以守護線程也會終止,虛擬機也同樣退出
b. 反過來,只要任何用戶線程還在運行,守護線程就不會終止,虛擬機就不會退出
3.線程優(yōu)先級
3.1 表示
線程優(yōu)先級分為10個級別,分別用Thread類常量表示。
3.2 設(shè)置
通過方法setPriority(int grade)進行優(yōu)先級設(shè)置,默認線程優(yōu)先級是5,即 Thread.NORM_PRIORITY。
4.線程狀態(tài)
創(chuàng)建狀態(tài):當(dāng)用 new 操作符創(chuàng)建一個線程的時候
就緒狀態(tài):調(diào)用 start 方法,處于就緒狀態(tài)的線程并不一定馬上就會執(zhí)行 run 方法,還需要等待CPU的調(diào)度
運行狀態(tài):CPU 開始調(diào)度線程,并開始執(zhí)行 run 方法
阻塞(掛起)狀態(tài):線程的執(zhí)行過程中由于一些原因進入阻塞狀態(tài),比如:調(diào)用 sleep/wait 方法、嘗試去得到一個鎖等
結(jié)束(消亡)狀態(tài):run 方法執(zhí)行完 或者 執(zhí)行過程中遇到了一個異常
(1)start()和run()的區(qū)別
通過調(diào)用Thread類的start()方法來啟動一個線程,這時此線程是處于就緒狀態(tài),并沒有運行。調(diào)用Thread類調(diào)用run()方法來完成其運行操作的,方法run()稱為線程體,它包含了要執(zhí)行的這個線程的內(nèi)容,run()運行結(jié)束,此線程終止,然后CPU再調(diào)度其它線程。
(2)sleep()、wait()、yield()的區(qū)別
sleep()方法屬于Thread類,wait()方法屬于Object類。
調(diào)用sleep()方法,線程不會釋放對象鎖,只是暫停執(zhí)行指定的時間,會自動恢復(fù)運行狀態(tài);調(diào)用wait()方法,線程會放棄對象鎖,進入等待此對象的等待鎖定池,不調(diào)用notify()方法,線程永遠處于就緒(掛起)狀態(tài)。
yield()直接由運行狀態(tài)跳回就緒狀態(tài),表示退讓線程,讓出CPU,讓CPU調(diào)度器重新調(diào)度。禮讓可能成功,也可能不成功,也就是說,回到調(diào)度器和其他線程進行公平競爭。
1.Android線程的原則
(1)為什么不能再主線程中做耗時操作
防止ANR, 不能在UI主線程中做耗時的操作,因此我們可以把耗時的操作放在另一個工作線程中去做。操作完成后,再通知UI主線程做出相應(yīng)的響應(yīng)。這就需要掌握線程間通信的方式了。 在Android中提供了兩種線程間的通信方式:一種是AsyncTask機制,另一種是Handler機制。
(2)為什么不能在非UI線程中更新UI 因為Android的UI線程是非線程安全的,應(yīng)用更新UI,是調(diào)用invalidate()方法來實現(xiàn)界面的重繪,而invalidate()方法是非線程安全的,也就是說當(dāng)我們在非UI線程來更新UI時,可能會有其他的線程或UI線程也在更新UI,這就會導(dǎo)致界面更新的不同步。因此我們不能在非UI主線程中做更新UI的操作。
2.Android實現(xiàn)多線程的幾種方式
3.為何需要多線程
多線程的本質(zhì)就是異步處理,直觀一點說就是不要讓用戶感覺到“很卡”。
4.多線程機制的核心是啥
多線程核心機制是Handler
推薦Handler講解視頻: 面試總被問到Handler?帶你從源碼的角度解讀Handler核心機制
根據(jù)上方提到的 多進程、多線程、Handler 問題,我整理了一套 Binder與Handler 機制解析的學(xué)習(xí)文檔,提供給大家進行學(xué)習(xí)參考,有需要的可以 點擊這里直接獲取!!! 里面記錄許多Android 相關(guān)學(xué)習(xí)知識點。
異步通信機制,將工作線程中需更新UI的操作信息 傳遞到 UI主線程,從而實現(xiàn) 工作線程對UI的更新處理,最終實現(xiàn)異步消息的處理。Handler不僅僅能將子線程的數(shù)據(jù)傳遞給主線程,它能實現(xiàn)任意兩個線程的數(shù)據(jù)傳遞。
(1)Message
Message 可以在線程之間傳遞消息。可以在它的內(nèi)部攜帶少量數(shù)據(jù),用于在不同線程之間進行數(shù)據(jù)交換。除了 what 字段,還可以使用 arg1 和 arg2 來攜帶整型數(shù)據(jù),使用 obj 來攜帶 Object 數(shù)據(jù)。
(2) Handler
Handler 作為處理中心,用于發(fā)送(sendMessage 系列方法)與處理消息(handleMessage 方法)。
(3) MessageQueue
MessageQueue 用于存放所有通過 Handler 發(fā)送的消息。這部分消息會一直存放在消息隊列中,直到被處理。每個線程中只會有一個 MessageQueue 對象
(4) Looper
Looper 用于管理 MessageQueue 隊列,Looper對象通過loop()方法開啟了一個死循環(huán)——for (;;){},不斷地從looper內(nèi)的MessageQueue中取出Message,并傳遞到 Handler 的 handleMessage() 方法中。每個線程中只會有一個 Looper 對象。
AsyncTask 是一種輕量級的任務(wù)異步類,可以在后臺子線程執(zhí)行任務(wù),且將執(zhí)行進度及執(zhí)行結(jié)果傳遞給 UI 線程。
(1)onPreExecute()
在 UI 線程上工作,在任務(wù)執(zhí)行 doInBackground() 之前調(diào)用。此步驟通常用于設(shè)置任務(wù),例如在用戶界面中顯示進度條。
(2)doInBackground(Params... params)
在子線程中工作,在 onPreExecute() 方法結(jié)束后執(zhí)行,這一步被用于在后臺執(zhí)行長時間的任務(wù),Params 參數(shù)通過 execute(Params) 方法被傳遞到此方法中。任務(wù)執(zhí)行結(jié)束后,將結(jié)果傳遞給 onPostExecute(Result) 方法,同時我們可以通過 publishProgress(Progress) 方法,將執(zhí)行進度發(fā)送給 onProgressUpdate(Progress) 方法。
(3)onProgressUpdate(Progress... values)
在 UI 線程上工作,會在 doInBackground() 中調(diào)用 publishProgress(Progress) 方法后執(zhí)行,此方法用于在后臺計算仍在執(zhí)行時(也就是 doInBackgound() 還在執(zhí)行時)將計算執(zhí)行進度通過 UI 顯示出來。例如,可以通過動畫進度條或顯示文本字段中的日志,從而方便用戶知道后臺任務(wù)執(zhí)行的進度。
(4)onPostExecute(Result result)
在 UI 線程上工作,在任務(wù)執(zhí)行完畢(即 doInBackground(Result) 執(zhí)行完畢)并將執(zhí)行結(jié)果傳過來的時候工作。
使用規(guī)則:
(1)AsyncTask 是個抽象類,所以要創(chuàng)建它的子類實現(xiàn)抽象方法
(1)AsyncTask 類必須是在 UI 線程中被加載,但在Android 4.1(API 16)開始,就能被自動加載完成。
(2)AsyncTask 類的實例對象必須在 UI 線程中被創(chuàng)建。
(3)execute() 方法必須是在 UI 線程中被調(diào)用。
(4)不要手動調(diào)用方法 onPreExecute()、onPostExecute()、doInBackground()、onProgressUpdate()
(5)任務(wù)只能執(zhí)行一次(如果嘗試第二次執(zhí)行,將拋出異常)。即一個AsyncTask對象只能調(diào)用一次execute()方法。
原理:
? ? ? 其源碼中原理還是 Thread 與 Handler 的實現(xiàn),其包含 兩個線程池,一個 Handler,如下所示:
名稱類型作用
SERIAL_EXECUTOR線程池分發(fā)任務(wù),串行分發(fā),一次只分發(fā)一個任務(wù)
THREAD_POOL_EXECUTOR線程池執(zhí)行任務(wù),并行執(zhí)行,執(zhí)行的任務(wù)由 SERIAL_EXECUTOR 分發(fā)
InternalHandlerHandler負責(zé)子線程與主線程的溝通,通知主線程做 UI 工作
一方面減少了每個并行任務(wù)獨自建立線程的開銷,另一方面可以管理多個并發(fā)線程的公共資源,從而提高了多線程的效率。所以ThreadPoolExecutor比較適合一組任務(wù)的執(zhí)行。Executors利用工廠模式對ThreadPoolExecutor進行了封裝。
Executors提供了四種創(chuàng)建ExecutorService的方法,他們的使用場景如下:
1. Executors.newFixedThreadPool()
創(chuàng)建一個定長的線程池,每提交一個任務(wù)就創(chuàng)建一個線程,直到達到池的最大長度,這時線程池會保持長度不再變化。
當(dāng)線程處于空閑狀態(tài)時,它們并不會被回收,除非線程池被關(guān)閉。當(dāng)所有的線程都處于活動狀態(tài)時,新任務(wù)都會處于等待狀態(tài),直到有線程空閑出來。
只有核心線程并且不會被回收,能夠更加快速的響應(yīng)外界的請求。
2. Executors.newCachedThreadPool()
創(chuàng)建一個可緩存的線程池,如果當(dāng)前線程池的長度超過了處理的需要時,它可以靈活的回收空閑的線程,當(dāng)需要增加時,它可以靈活的添加新的線程,而不會對池的長度作任何限制
線程數(shù)量不定的線程池,只有非核心線程,最大線程數(shù)為 Integer.MAX_VALUE。當(dāng)線程池中的線程都處于活動狀態(tài)時,線程池會創(chuàng)建新的線程來處理新任務(wù),否則利用空閑的線程來處理新任務(wù)。線程池中的空閑線程具有超時機制,為 60s。
任務(wù)隊列相當(dāng)于一個空集合,導(dǎo)致任何任務(wù)都會立即被執(zhí)行,適合執(zhí)行大量耗時較少的任務(wù)。當(dāng)整個線程池都處于限制狀態(tài)時,線程池中的線程都會超時而被停止。
3. Executors.newScheduledThreadPool()
創(chuàng)建一個定長的線程池,而且支持定時的以及周期性的任務(wù)執(zhí)行,類似于Timer。
非核心線程數(shù)沒有限制,并且非核心線程閑置的時候立即回收,主要用于執(zhí)行定時任務(wù)和具有固定周期的重復(fù)任務(wù)。
4. Executors.newSingleThreadExecutor()
創(chuàng)建一個單線程化的executor,它只創(chuàng)建唯一的worker線程來執(zhí)行任務(wù)
只有一個核心線程,保證所有的任務(wù)都在一個線程中順序執(zhí)行,意義在于不需要處理線程同步的問題。
一般用于執(zhí)行后臺耗時任務(wù),當(dāng)任務(wù)執(zhí)行完成會自動停止;同時由于它是一個服務(wù),優(yōu)先級要遠遠高于線程,更不容易被系統(tǒng)殺死,因此比較適合執(zhí)行一些高優(yōu)先級的后臺任務(wù)。
使用步驟:創(chuàng)建IntentService的子類,重寫onHandleIntent方法,在onHandleIntent中執(zhí)行耗時任務(wù)
原理:在源碼實現(xiàn)上,IntentService封裝了HandlerThread和Handler。onHandleIntent方法結(jié)束后會調(diào)用IntentService的stopSelf(int startId)方法嘗試停止服務(wù)。
IntentService的內(nèi)部是通過消息的方式請求HandlerThread執(zhí)行任務(wù),HandlerThread內(nèi)部又是一種使用Handler的Thread,這就意味著IntentService和Looper一樣是順序執(zhí)行后臺任務(wù)的
(HandlerThread:封裝了Handler + ThreadHandlerThread適合在有需要一個工作線程(非UI線程)+任務(wù)的等待隊列的形式,優(yōu)點是不會有堵塞,減少了對性能的消耗,缺點是不能同時進行多個任務(wù)的處理,需要等待進行處理。處理效率低,可以當(dāng)成一個輕量級的線程池來用)
多線程作為Android開發(fā)中相對而言較為高階的知識,其中用到相關(guān)的知識點是非常的多,所以在我們需要進行設(shè)計或者寫多線程的代碼就必須要進行相對謹慎的處理,這樣就由必要對其要有著比較系統(tǒng)化的認知
我們一般將Android應(yīng)用分成為兩種:主線程和工作線程;主線程主要是用來進行初始化UI,而工作線程主要是進行耗時操作,例如讀取數(shù)據(jù)庫,網(wǎng)絡(luò)連接等
Android系統(tǒng)是以進程為單位來對應(yīng)用程序資源進行限制,這個問題的可以解釋為:一個進程最多能夠開幾個線程?最好能開幾個?但實則這個是沒有上限這一說,主要是因為資源的限制
Android中關(guān)于主線程的理解:Android的主線程是UI線程,在Android中,四大組件運行在主線程中,在主線程中做耗時操作會導(dǎo)致程序出現(xiàn)卡頓甚至出現(xiàn)ANR異常,一個.
在一個程序中,這些獨立運行的程序片斷叫作“線程”(Thread),利用它編程的概念就叫作“多線程處理”。多線程處理一個常見的例子就是用戶界面。
線程總的來就是進程的一個實體,是CPU進行分派和調(diào)度的基本單位,擁有著比進程更小且能夠獨立運行的基本單位,線程本身基本上是不擁有系統(tǒng)資源,僅擁有一點在運行過程中必須擁有的資源,但它可與同屬一個進程中的其他進程進行共享其所擁有的所有資源
線程狀態(tài)有些地方將之分為5中狀態(tài),而且在Java Jdk中線程被其定義為6中狀態(tài),我們可以對其進行類比
普遍定義的5中狀態(tài):新建,就緒,運行,阻塞, 死亡
Java Jdk 定義狀態(tài)
線程阻塞是指在某一時刻的某一個線程在進行運行一段代碼的情況下,突然另一個線程也要進行運行,但在運行過程中,那個線程執(zhí)行完全運行之前,另一個線程是不可能獲取到CPU的執(zhí)行權(quán),就會導(dǎo)致線路阻塞的出現(xiàn)
死鎖也稱之為抱死,意思就是說一個進程鎖定了另外一個進程所需要的頁或表是,但第二個進程同時又鎖定了第一個進程所需的一頁,這樣就會出現(xiàn)死鎖現(xiàn)象
簡要介紹實現(xiàn)線程的三種方式:繼承Thread,實現(xiàn)runnable,實現(xiàn)callable。這里有一點需要注意的是,實現(xiàn)callable是與線程池相關(guān)聯(lián)的而callable很重要的一個特性是其帶有返回值。當(dāng)我們只需實現(xiàn)單線程時實現(xiàn)runnable更加利于線程程序的拓展
在線程開啟之前進行調(diào)用 thread.setDaemon(true); 將thread設(shè)定成當(dāng)前線程中的守護線程 使用案例
線程讓步【yield方法】讓當(dāng)前線程釋放CPU資源,讓其他線程搶占
這種具體某個對象鎖 wait notify 方法與Condition 的 await以及signal方法類似; 全面這種方法的阻塞等待都可以是釋放鎖,而且在喚醒后,這種線程都是能夠獲取鎖資源的,而這個門栓就跟閥門類似
文章標(biāo)題:android的多線程,android多線程并發(fā)處理
網(wǎng)頁路徑:http://chinadenli.net/article25/dsgigci.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供移動網(wǎng)站建設(shè)、企業(yè)建站、靜態(tài)網(wǎng)站、響應(yīng)式網(wǎng)站、品牌網(wǎng)站建設(shè)、Google
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)