導航:首頁 > 操作系統 > android在主線程執行

android在主線程執行

發布時間:2022-09-26 14:35:20

A. android 更新ui是在主線程還是子線程

在一個Android 程序開始運行的時候,會單獨啟動一個Process。默認的情況下,所有這個程序中的Activity或者Service(Service和 Activity只是Android提供的Components中的兩種,除此之外還有Content Provider和Broadcast Receiver)都會跑在這個Process。 一個Android 程序默認情況下也只有一個Process,但一個Process下卻可以有許多個Thread。在這么多Thread當中,有一個Thread,我們稱之為UI Thread。UI Thread在Android程序運行的時候就被創建,是一個Process當中的主線程Main Thread,主要是負責控制UI界面的顯示、更新和控制項交互。在Android程序創建之初,一個Process呈現的是單線程模型,所有的任務都在一個線程中運行。因此,我們認為,UI Thread所執行的每一個函數,所花費的時間都應該是越短越好。而其他比較費時的工作(訪問網路,下載數據,查詢資料庫等),都應該交由子線程去執行,以免阻塞主線程。 那麼,UI Thread如何和其他Thread一起工作呢?常用方法是: 誕生一個主線程的Handler物件,當做Listener去讓子線程能將訊息Push到主線程的Message Quene里,以便觸發主線程的handlerMessage()函數,讓主線程知道子線程的狀態,並在主線程更新UI。

B. Android進程間和線程間通信方式

        進程:是具有一定獨立功能的程序關於某個數據集合上的一次運行活動,進程是系統進行資源分配和調度的一個獨立單位。

  線程:是進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位。線程自己基本上不擁有系統資源,只擁有一些在運行中必不可少的資源(如程序計數器,一組寄存器和棧),但是它可與同屬一個進程的其他的線程共享進程所擁有的全部資源。

  區別:

  (1)、一個程序至少有一個進程,一個進程至少有一個線程;

  (2)、線程的劃分尺度小於進程,使得多線程程序的並發性高;

  (3)、進程在執行過程中擁有獨立的內存單元,而多個線程共享內存,但線程之間沒有單獨的地址空間,一個線程死掉就等於整個進程死掉。

---------------------

一、Android進程間通信方式

1.Bundle

  由於Activity,Service,Receiver都是可以通過Intent來攜帶Bundle傳輸數據的,所以我們可以在一個進程中通過Intent將攜帶數據的Bundle發送到另一個進程的組件。

  缺點:無法傳輸Bundle不支持的數據類型。

2.ContentProvider

  ContentProvider是Android四大組件之一,以表格的方式來儲存數據,提供給外界,即Content Provider可以跨進程訪問其他應用程序中的數據。用法是繼承ContentProvider,實現onCreate,query,update,insert,delete和getType方法,onCreate是負責創建時做一些初始化的工作,增刪查改的方法就是對數據的查詢和修改,getType是返回一個String,表示Uri請求的類型。注冊完後就可以使用ContentResolver去請求指定的Uri。

3.文件

  兩個進程可以到同一個文件去交換數據,我們不僅可以保存文本文件,還可以將對象持久化到文件,從另一個文件恢復。要注意的是,當並發讀/寫時可能會出現並發的問題。

4.Broadcast

  Broadcast可以向android系統中所有應用程序發送廣播,而需要跨進程通訊的應用程序可以監聽這些廣播。

5.AIDL方式

  Service和Content Provider類似,也可以訪問其他應用程序中的數據,Content Provider返回的是Cursor對象,而Service返回的是java對象,這種可以跨進程通訊的服務叫AIDL服務。

         AIDL通過定義服務端暴露的介面,以提供給客戶端來調用,AIDL使伺服器可以並行處理,而Messenger封裝了AIDL之後只能串列運行,所以Messenger一般用作消息傳遞。

6.Messenger

  Messenger是基於AIDL實現的,服務端(被動方)提供一個Service來處理客戶端(主動方)連接,維護一個Handler來創建Messenger,在onBind時返回Messenger的binder。

  雙方用Messenger來發送數據,用Handler來處理數據。Messenger處理數據依靠Handler,所以是串列的,也就是說,Handler接到多個message時,就要排隊依次處理。

7.Socket

  Socket方法是通過網路來進行數據交換,注意的是要在子線程請求,不然會堵塞主線程。客戶端和服務端建立連接之後即可不斷傳輸數據,比較適合實時的數據傳輸

二、Android線程間通信方式

  一般說線程間通信主要是指主線程(也叫UI線程)和子線程之間的通信,主要有以下兩種方式:

1.AsyncTask機制

  AsyncTask,非同步任務,也就是說在UI線程運行的時候,可以在後台的執行一些非同步的操作;AsyncTask可以很容易且正確地使用UI線程,AsyncTask允許進行後台操作,並在不顯示使用工作線程或Handler機制的情況下,將結果反饋給UI線程。但是AsyncTask只能用於短時間的操作(最多幾秒就應該結束的操作),如果需要長時間運行在後台,就不適合使用AsyncTask了,只能去使用Java提供的其他API來實現。

2.Handler機制

  Handler,繼承自Object類,用來發送和處理Message對象或Runnable對象;Handler在創建時會與當前所在的線程的Looper對象相關聯(如果當前線程的Looper為空或不存在,則會拋出異常,此時需要在線程中主動調用Looper.prepare()來創建一個Looper對象)。使用Handler的主要作用就是在後面的過程中發送和處理Message對象和讓其他的線程完成某一個動作(如在工作線程中通過Handler對象發送一個Message對象,讓UI線程進行UI的更新,然後UI線程就會在MessageQueue中得到這個Message對象(取出Message對象是由其相關聯的Looper對象完成的),並作出相應的響應)。

三、Android兩個子線程之間通信

  面試的過程中,有些面試官可能會問Android子線程之間的通信方式,由於絕大部分程序員主要關注的是Android主線程和子線程之間的通信,所以這個問題很容易讓人懵逼。

  主線程和子線程之間的通信可以通過主線程中的handler把子線程中的message發給主線程中的looper,或者,主線程中的handler通過post向looper中發送一個runnable。但looper默認存在於main線程中,子線程中沒有Looper,該怎麼辦呢?其實原理很簡單,把looper綁定到子線程中,並且創建一個handler。在另一個線程中通過這個handler發送消息,就可以實現子線程之間的通信了。

  子線程創建handler的兩種方式:

  方式一:給子線程創建Looper對象:

new Thread(new Runnable() {

            public void run() { 

                Looper.prepare();  // 給這個Thread創建Looper對象,一個Thead只有一個Looper對象

                Handler handler = new Handler(){ 

                    @Override 

                    public void handleMessage(Message msg) { 

                        Toast.makeText(getApplicationContext(), "handleMessage", Toast.LENGTH_LONG).show(); 

                    } 

                }; 

                handler.sendEmptyMessage(1); 

                Looper.loop(); // 不斷遍歷MessageQueue中是否有消息

            }; 

        }).start();

---------------------

       方式二:獲取主線程的looper,或者說是UI線程的looper:

new Thread(new Runnable() {

            public void run() { 

                Handler handler = new Handler(Looper.getMainLooper()){ // 區別在這!!! 

                    @Override 

                    public void handleMessage(Message msg) { 

                        Toast.makeText(getApplicationContext(), "handleMessage", Toast.LENGTH_LONG).show(); 

                    } 

                }; 

                handler.sendEmptyMessage(1); 

            }; 

        }).start();

---------------------

C. Android 如何判斷當前代碼是否在主線程中執行

在java-mian線程中Thread.currentThread().getName() == "main";
你可以做個android程序在主線程里獲取當前線程名Thread.currentThread().getName();以後在其他線程里就獲取當前線程名與之比較Thread.currentThread().getName().equals("main");

D. android 怎麼執行主線程

可以。你這個問題是,android 能不能在 非主activity的 類B中,調用activity A的方法。
在B做一個activity的 變數。在B構造函數中 對context參數 保存,記得要對context 強制轉換類型 變為主線程的 activity。之後在B中就能靠activity變數調用 A的方法。
不過你這個是多線程,要用synchronize做好共享數據保護工作。

E. android訪問網路狀態是否可在主線程中執行

是的,android2.2版本以下是可以在主線程中執行網路訪問的,2.2以上就得重起一個線程了。

F. android四大組件回調函數哪些是在ui主線程執行

android 中為了提供交互的速度和效率,四大組件,如果不是在子線程的回調,都是在主線程。如果放在子線程中,會導致刷新很卡,無法很好地響應用戶的操作。
不要再提問了,去博客園問問看

G. 既然android service是運行在主線程中的,那service還有什麼用

你沒有將android 組件和android C/S架構的概念理解清楚,不僅沒有理解清楚,還把組件的概念,跟線程、進程混淆在一起了。 我將android比喻成一棟辦公大樓,android 中進程就是一個辦公室,線程就是辦公室裡面的員工,辦公室是不能幹活的,而真正幹活的是這個辦公室裡面的員工。一個員工只能在一個辦公室裡面幹活,而一個辦公室可以有很多員工。 Android的老闆希望它的公司能辦理的井井有條,於是針對每一種職能專門設立管理部門,例如WMS,負責窗口管理的,例如MPS,負責多媒體播放的。 一個部門可以有一個或多個辦公室,一個辦公室也可以有多個部門。 而android的管理部門往往是不幹什麼實事的,就像我們的天朝的猿類,你推它一下,它才動一下。所以android需要一些干實事的部門,做對外客戶的,這些部門我們統稱為apk。Android中有好多這種部門,於是為了防止這些部門瞎干,又把部門分成Activity、Service、BrocastReceiver、ContentProvider四種子部門,這些子部門就是用來跟其它部門做溝通的,而所有的子部門運作時都會由大管家AMS來記錄在案。 Activity,做門面的。 Service,做對外支持的。 BrocastReceiver,做門衛收信的。 ContentProvider,做倉庫管理的。 做門面的,可以做對外支持的活,也可以做倉庫管理的活。但是外面可不這么認為,它想找你要數據,只會找ContentProvier,找對外支持只會找Service。 另外AMS大管家有個不好的習慣,它為了節省公司的資源,AMS那裡沒有你這個apk任何部門運行記錄的時候,它有可能把你的電關了(殺進程)。 而LZ你描述的問題呢,就是你的部門想下載東西,是由Activity子部門去干呢,還是Service去干。

H. 每個Android 都應必須了解的多線程知識點~

進程是系統調度和資源分配的一個獨立單位。

在Android中,一個應用程序就是一個獨立的集成,應用運行在一個獨立的環境中,可以避免其他應用程序/進程的干擾。當我們啟動一個應用程序時,系統就會創建一個進程(該進程是從Zygote中fork出來的,有獨立的ID),接著為這個進程創建一個主線程,然後就可以運行MainActivity了,應用程序的組件默認都是運行在其進程中。開發者可以通過設置應用的組件的運行進程,在清單文件中給組件設置:android:process = "進程名";可以達到讓組件運行在不同進程中的目的。讓組件運行在不同的進程中,既有好處,也有壞處。我們依次的說明下。

好處:每一個應用程序(也就是每一個進程)都會有一個內存預算,所有運行在這個進程中的程序使用的總內存不能超過這個值,讓組件運行不同的進程中,可以讓主進程可以擁有更多的空間資源。當我們的應用程序比較大,需要的內存資源比較多時(也就是用戶會抱怨應用經常出現OutOfMemory時),可以考慮使用多進程。

壞處:每個進程都會有自己的虛擬機實例,因此讓在進程間共享一些數據變得相對困難,需要採用進程間的通信來實現數據的共享。

線程是進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位。

在Android中,線程會有那麼幾種狀態:創建、就緒、運行、阻塞、結束。當應用程序有組件在運行時,UI線程是處於運行狀態的。默認情況下,應用的所有組件的操作都是在UI線程里完成的,包括響應用戶的操作(觸摸,點擊等),組件生命周期方法的調用,UI的更新等。因此如果UI線程處理阻塞狀態時(在線程里做一些耗時的操作,如網路連接等),就會不能響應各種操作,如果阻塞時間達到5秒,就會讓程序處於ANR(application not response)狀態。

1.線程作用

減少程序在並發執行時所付出的時空開銷,提高操作系統的並發性能。

2.線程分類

守護線程、非守護線程(用戶線程)

2.1 守護線程

定義:守護用戶線程的線程,即在程序運行時為其他線程提供一種通用服務
常見:如垃圾回收線程
設置方式:thread.setDaemon(true);//設置該線程為守護線程

2.2 非守護線程(用戶線程)

主線程 & 子線程。

2.2.1 主線程(UI線程)

定義:Android系統在程序啟動時會自動啟動一條主線程
作用:處理四大組件與用戶進行交互的事情(如UI、界面交互相關)
因為用戶隨時會與界面發生交互,因此主線程任何時候都必須保持很高的響應速度,所以主線程不允許進行耗時操作,否則會出現ANR。

2.2.2 子線程(工作線程)

定義:手動創建的線程
作用:耗時的操作(網路請求、I/O操作等)

2.3 守護線程與非守護線程的區別和聯系

區別:虛擬機是否已退出,即
a. 當所有用戶線程結束時,因為沒有守護的必要,所以守護線程也會終止,虛擬機也同樣退出
b. 反過來,只要任何用戶線程還在運行,守護線程就不會終止,虛擬機就不會退出

3.線程優先順序

3.1 表示

線程優先順序分為10個級別,分別用Thread類常量表示。

3.2 設置

通過方法setPriority(int grade)進行優先順序設置,默認線程優先順序是5,即 Thread.NORM_PRIORITY。

4.線程狀態

創建狀態:當用 new 操作符創建一個線程的時候

就緒狀態:調用 start 方法,處於就緒狀態的線程並不一定馬上就會執行 run 方法,還需要等待CPU的調度

運行狀態:CPU 開始調度線程,並開始執行 run 方法

阻塞(掛起)狀態:線程的執行過程中由於一些原因進入阻塞狀態,比如:調用 sleep/wait 方法、嘗試去得到一個鎖等

結束(消亡)狀態:run 方法執行完 或者 執行過程中遇到了一個異常

(1)start()和run()的區別

通過調用Thread類的start()方法來啟動一個線程,這時此線程是處於就緒狀態,並沒有運行。調用Thread類調用run()方法來完成其運行操作的,方法run()稱為線程體,它包含了要執行的這個線程的內容,run()運行結束,此線程終止,然後CPU再調度其它線程。

(2)sleep()、wait()、yield()的區別

sleep()方法屬於Thread類,wait()方法屬於Object類。
調用sleep()方法,線程不會釋放對象鎖,只是暫停執行指定的時間,會自動恢復運行狀態;調用wait()方法,線程會放棄對象鎖,進入等待此對象的等待鎖定池,不調用notify()方法,線程永遠處於就緒(掛起)狀態。

yield()直接由運行狀態跳回就緒狀態,表示退讓線程,讓出CPU,讓CPU調度器重新調度。禮讓可能成功,也可能不成功,也就是說,回到調度器和其他線程進行公平競爭。

1.Android線程的原則

(1)為什麼不能再主線程中做耗時操作
防止ANR, 不能在UI主線程中做耗時的操作,因此我們可以把耗時的操作放在另一個工作線程中去做。操作完成後,再通知UI主線程做出相應的響應。這就需要掌握線程間通信的方式了。 在Android中提供了兩種線程間的通信方式:一種是AsyncTask機制,另一種是Handler機制。

(2)為什麼不能在非UI線程中更新UI 因為Android的UI線程是非線程安全的,應用更新UI,是調用invalidate()方法來實現界面的重繪,而invalidate()方法是非線程安全的,也就是說當我們在非UI線程來更新UI時,可能會有其他的線程或UI線程也在更新UI,這就會導致界面更新的不同步。因此我們不能在非UI主線程中做更新UI的操作。

2.Android實現多線程的幾種方式

3.為何需要多線程

多線程的本質就是非同步處理,直觀一點說就是不要讓用戶感覺到「很卡」。

4.多線程機制的核心是啥

多線程核心機制是Handler

推薦Handler講解視頻: 面試總被問到Handler?帶你從源碼的角度解讀Handler核心機制

根據上方提到的 多進程、多線程、Handler 問題,我整理了一套 Binder與Handler 機制解析的學習文檔,提供給大家進行學習參考,有需要的可以 點擊這里直接獲取!!! 裡面記錄許多Android 相關學習知識點。

I. android中主線程執行時,子線程執行嗎

執行,但一般不與視圖交互,因為在android 中還有一個headler概念,我對這塊也不是特別清楚

J. Android可以讓主線程在其他子線程執行完後再執行嗎如果可以,該怎麼做

android中什麼時候會選擇用廣播來進行線程間的通信 Android 多線程 通信 線程中通信就不要用廣播了吧 進程中通信可以用廣播或者aidl 可是,這兩天看到的項目都是這么做的;然後,自己分析了下,覺得一下的理由也是可以成立的; 1.正常情況下我們選擇handler消息機制來進行單向的線程間的通信;(工作線程向主線程發送消息) 因為主線程有現成的handler,而工作線程沒有現成的handler,這樣的話,主線程將handler交給工作線程而讓工作線程將工作的結果交給主線程; 相反,工作線程中沒有現成的handler(事實上是沒有消息隊列,也就是handler沒有綁定到工作線程),那麼,如果開辟的話,代碼角度上是挺麻煩的(相對應廣播機制來說); 2.廣播機制本身就是雙向的(工作線程向主線程發送廣播,主線程向工作線程發送廣播); //另外,對於像一個activity中通過fragment來進行界面的處理; 我們大多數情況下是採用廣播的機制來實現fragment中adapter的數據的更新;這樣做主要是考慮到工作線程的任務載入完成,而具體的對應刷新的activity可能還沒有啟動; 另外,基於介面隔離原則,如果用handler進行通信的話,則不能很好的滿足這一原則; 你要是周期比較長 用廣播好些吧 應該與周期關系不是很密切。最主要的原因是兩條線成是雙向通信。 Handler類似於P2P的通信。 廣播則類似於一個server端,用來處理分發不同線程的請求,從控制器的角度來說用廣播更好一點。 一般使用Handler的,多用於子線程處理事務,完成時告知主線程這一類的情況。 而類似樓主所說的多條線程之間需要頻繁交互的話,廣播是個很好的選擇,並且結構清晰,只是不知道廣播的性能與handler相比會怎麼樣。

閱讀全文

與android在主線程執行相關的資料

熱點內容
程序員用得到數字區嗎 瀏覽:174
python求商 瀏覽:477
ipad能用c語言編譯器嗎 瀏覽:561
軟泥解壓球最新版 瀏覽:998
4萬程序員辭職創業 瀏覽:759
thinkingphp 瀏覽:597
安卓相冊移動文件夾 瀏覽:6
耳朵清潔解壓聲控99的人都睡得著 瀏覽:205
叉車出租網站源碼 瀏覽:874
共享單車的app是什麼 瀏覽:408
不帶gui的伺服器什麼意思 瀏覽:373
金剛經及PDF 瀏覽:102
php中冒號 瀏覽:358
php5432 瀏覽:352
命令在哪使用 瀏覽:172
php獲取網頁元素 瀏覽:708
為什麼需要硬體驅動編譯 瀏覽:885
pm編程怎樣看導柱孔對不對稱 瀏覽:138
農業大學選課找不到伺服器怎麼辦 瀏覽:659
路由配置網關命令 瀏覽:935