當前位置:首頁 » 安卓系統 » android的線程

android的線程

發布時間: 2024-10-21 08:09:22

1. Android主線程到底是什麼

  • Android中關於主線程的理解:

Android的主線程是UI線程,在Android中,四大組件運行在主線程中,在主線程中做耗時操作會導致程序出現卡頓甚至出現ANR異常,一個基本常識就是將耗時操作放到子線程中去處理,然後通過Handler回調到主線程。

  • 有三點還需要注意:

  1. 因為四大組件運行在一個主線程中,那麼若果當前界面在顯示的時候,後台的activity仍有處理邏輯再運行的話,仍然會造成當前界面的卡頓。

  2. 通過Handler回調到主線程只是避免程序出現ANR的第一步,必須要注意handler中邏輯處理的耗時,如果將很多消息都扔給了handler,那麼也會給主線程造成壓力,導致程序運行卡頓。

  3. 四大組件、Handler都是在一個線程中,那麼主線程在同一時刻不可能發送兩個廣播,換句話說就是若果能夠保證所有的廣播都是在主線程中發送,那麼廣播內部其實不需要加上對非同步操作的處理。

2. android開發中線程有幾種狀態,分別是哪些

【答案】:1)、新建狀態(New):新創建了一個線程對象。
2)、就緒狀態(Runnable):線程對象創建後,其他線程調用了該對象的start()方法。該狀態的線程位於可運行線程池中,變得可運行,等待獲取CPU的使用權。
3)、運行狀態(Running):就緒狀態的線程獲取了CPU,執行run()方法。
4)、阻塞狀態(Blocked):阻塞狀態是線程因為某種原因放棄CPU使用權,暫時停止運行。直到線程進入就緒狀態,才有機會轉到運行狀態。阻塞的情況分三種:
(一)、等待阻塞:運行的線程執行wait()方法,JVM會把該線程放入等待池中。
(二)、同步阻塞:運行的線程在獲取對象的同步鎖時,若該同步鎖被別的線程佔用,則JVM會把該線程放入鎖池中。
(三)、其他阻塞:運行的線程執行sleep()或join()方法,或者發出了I/O請求時,JVM會把該線程置為阻塞狀態。當sleep()狀態超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程重新轉入就緒狀態。
5)、死亡狀態(Dead):線程執行完了或者因異常退出了run()方法,該線程結束生命周期。
當調用start方法的時候,該線程就進入就緒狀態。等待CPU進行調度執行,此時還沒有真正執行線程。
當調用run方法的時候,是已經被CPU進行調度,執行線程的主要任務。

3. 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串列與並行

五、線程池

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

4. android 主線程和子線程有什麼區別

本文較為深入的分析了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。
例如,在子線程的狀態發生變化時,我們需要更新UI。如果在子線程中直接更新UI,通常會拋出下面的異常:
11-07 13:33:04.393: ERROR/JavaBinder(1029):android.view.ViewRoot$:Only the original thread that created a view hierarchy can touch its views.
意思是,無法在子線程中更新UI。為此,我們需要通過Handler物件,通知主線程Ui Thread來更新界面。
如下,首先創建一個Handler,來監聽Message的事件:

private final int UPDATE_UI = 1;
private Handler mHandler = new MainHandler();

private class MainHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case UPDATE_UI: {
Log.i("TTSDeamon", "UPDATE_UI");
showTextView.setText(editText.getText().toString());
ShowAnimation();
break;
}
default:
break;
}
}
}

或者:

private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case UPDATE_UI: {
Log.i("TTSDeamon", "UPDATE_UI");
showTextView.setText(editText.getText().toString());
ShowAnimation();
break;
}
default:
break;
}
}
}

當子線程的狀態發生變化,則在子線程中發出Message,通知更新UI。

mHandler.sendEmptyMessageDelayed(UPDATE_UI, 0);

在我們的程序中,很多Callback方法有時候並不是運行在主線程當中的,所以如果在Callback方法中更新UI失敗,也可以採用上面的方法。

5. android啟動後怎麼查看其裡面的進程和線程

. Android中進程與進程、線程與線程之間如何通信?
1)一個 Android 程序開始運行時,會單獨啟動一個Process。
默認情況下,所有這個程序中的Activity或者Service都會跑在這個Process。
默認情況下,一個Android程序也只有一個Process,但一個Process下卻可以有許多個Thread。
2)一個 Android 程序開始運行時,就有一個主線程Main Thread被創建。該線程主要負責UI界面的顯示、更新和控制項交互,所以又叫UI Thread。

3)一個Android程序創建之初,一個Process呈現的是單線程模型--即MainThread,所有的任務都在一個線程中運行,所以,MainThread所調用的每一個函數,其耗時應該越短越好,而對於比較耗時的工作,應該交給子線程去做,以避免主線程(UI線程)被阻塞,導致程序出現ANR(Application not response)

一個Activity就運行在一個線程中嗎?或者編碼時,如果不是明確安排在不同線程中的兩個Activity,其就都是在同一個線程中?那從一個Activity跳轉到另一個Activity時,是不是跳出的那個Activity就處在睡眠狀態了?
【答】 每個Activity都有一個Process屬性,可以指定該Activity是屬於哪個進程的。當然如果不明確指明,應該就是從屬於默認進程(Application指定的,如其未指定,應該就是默認主進程)。

Android中有Task的概念,而同一個Task的各個Activity會形成一個棧,只有站定的Activity才有機會與用戶交互。

原文地址:Android中的進程與線程 原文作者:江鵬

當應用程序的組件第一次運行時,Android將啟動一個只有一個執行線程的Linux進程。默認,應用程序所有的組件運行在這個進程和線程中。然而,你可以安排組件運行在其他進程中,且你可以為進程衍生出其它線程。本文從下面幾點來介紹Android的進程與線程:

1、進程

組件運行於哪個進程中由清單文件控制。組件元素——<activity>、<service>、<receiver>、<provider>,都有一個process屬性可以指定組件運行在哪個進程中。這個屬性可以設置為每個組件運行在自己的進程中,或者某些組件共享一個進程而其他的不共享。他們還可以設置為不同應用程序的組件運行在同一個進程中——假設這些應用程序共享同一個Linux用戶ID且被分配了同樣的許可權。<application>元素也有process屬性,為所有的組件設置一個默認值。

所有的組件都在特定進程的主線程中實例化,且系統調用組件是由主線程派遣。不會為每個實例創建單獨的線程,因此,對應這些調用的方法——諸如View.onKeyDown()報告用用戶的行為和生命周期通知,總是運行在進程的主線程中。這意味著,沒有組件當被系統調用時應該執行很長時間或阻塞操作(如網路操作或循環計算),因為這將阻塞進程中的其它組件。你可以為長操作衍生獨立的線程。

public boolean onKeyDown(int keyCode,KeyEvent event):默認實現KeyEvent.Callback.onKeyMultiple(),當按下視圖的KEYCODE_DPAD_CENTER或KEYCODE_ENTER然後釋放時執行,如果視圖可用且可點擊。

參數

keyCode-表示按鈕被按下的鍵碼,來自KeyEvent
event-定義了按鈕動作的KeyEvent對象

返回值

如果你處理事件,返回true;如果你想下一個接收者處理事件,返回false。

當內存剩餘較小且其它進程請求較大內存並需要立即分配,Android要回收某些進程,進程中的應用程序組件會被銷毀。當他們再次運行時,會重新開始一個進程。

當決定終結哪個進程時,Android會權衡他們對用戶重要性的相對權值。例如,與運行在屏幕可見的活動進程相比(前台進程),它更容易關閉一個進程,它的活動在屏幕是不可見(後台進程)。決定是否終結進程,取決於運行在進程中的組件狀態。關於組件的狀態,將在後面一篇——組件生命周期中介紹。

2、線程

雖然你可能會將你的應用程序限制在一個進程中,但有時候你會需要衍生一個線程做一些後台工作。因為用戶界面必須很快地響應用戶的操作,所以活動寄宿的線程不應該做一些耗時的操作如網路下載。任何不可能在短時間完成的操作應該分配到別的線程。

線程在代碼中是用標準的Java線程對象創建的,Android提供了一些方便的類來管理線程——Looper用於在線程中運行消息循環、Handler用戶處理消息、HandlerThread用戶設置一個消息循環的線程。

Looper類

該類用戶在線程中運行消息循環。線程默認沒有消息循環,可以在線程中調用prepare()創建一個運行循環;然後調用loop()處理消息直到循環結束。大部分消息循環交互是通過Handler類。下面是一個典型的執行一個Looper線程的例子,分別使用prepare()和loop()創建一個初始的Handler與Looper交互:

1. Android中進程與進程、線程與線程之間如何通信?
1)一個 Android 程序開始運行時,會單獨啟動一個Process。
默認情況下,所有這個程序中的Activity或者Service都會跑在這個Process。
默認情況下,一個Android程序也只有一個Process,但一個Process下卻可以有許多個Thread。
2)一個 Android 程序開始運行時,就有一個主線程Main Thread被創建。該線程主要負責UI界面的顯示、更新和控制項交互,所以又叫UI Thread。

3)一個Android程序創建之初,一個Process呈現的是單線程模型--即MainThread,所有的任務都在一個線程中運行,所以,MainThread所調用的每一個函數,其耗時應該越短越好,而對於比較耗時的工作,應該交給子線程去做,以避免主線程(UI線程)被阻塞,導致程序出現ANR(Application not response)

一個Activity就運行在一個線程中嗎?或者編碼時,如果不是明確安排在不同線程中的兩個Activity,其就都是在同一個線程中?那從一個Activity跳轉到另一個Activity時,是不是跳出的那個Activity就處在睡眠狀態了?
【答】 每個Activity都有一個Process屬性,可以指定該Activity是屬於哪個進程的。當然如果不明確指明,應該就是從屬於默認進程(Application指定的,如其未指定,應該就是默認主進程)。

Android中有Task的概念,而同一個Task的各個Activity會形成一個棧,只有站定的Activity才有機會與用戶交互。

原文地址:Android中的進程與線程 原文作者:江鵬

當應用程序的組件第一次運行時,Android將啟動一個只有一個執行線程的Linux進程。默認,應用程序所有的組件運行在這個進程和線程中。然而,你可以安排組件運行在其他進程中,且你可以為進程衍生出其它線程。本文從下面幾點來介紹Android的進程與線程:

1、進程

組件運行於哪個進程中由清單文件控制。組件元素——<activity>、<service>、<receiver>、<provider>,都有一個process屬性可以指定組件運行在哪個進程中。這個屬性可以設置為每個組件運行在自己的進程中,或者某些組件共享一個進程而其他的不共享。他們還可以設置為不同應用程序的組件運行在同一個進程中——假設這些應用程序共享同一個Linux用戶ID且被分配了同樣的許可權。<application>元素也有process屬性,為所有的組件設置一個默認值。

所有的組件都在特定進程的主線程中實例化,且系統調用組件是由主線程派遣。不會為每個實例創建單獨的線程,因此,對應這些調用的方法——諸如View.onKeyDown()報告用用戶的行為和生命周期通知,總是運行在進程的主線程中。這意味著,沒有組件當被系統調用時應該執行很長時間或阻塞操作(如網路操作或循環計算),因為這將阻塞進程中的其它組件。你可以為長操作衍生獨立的線程。

public boolean onKeyDown(int keyCode,KeyEvent event):默認實現KeyEvent.Callback.onKeyMultiple(),當按下視圖的KEYCODE_DPAD_CENTER或KEYCODE_ENTER然後釋放時執行,如果視圖可用且可點擊。

參數

keyCode-表示按鈕被按下的鍵碼,來自KeyEvent
event-定義了按鈕動作的KeyEvent對象

返回值

如果你處理事件,返回true;如果你想下一個接收者處理事件,返回false。

當內存剩餘較小且其它進程請求較大內存並需要立即分配,Android要回收某些進程,進程中的應用程序組件會被銷毀。當他們再次運行時,會重新開始一個進程。

當決定終結哪個進程時,Android會權衡他們對用戶重要性的相對權值。例如,與運行在屏幕可見的活動進程相比(前台進程),它更容易關閉一個進程,它的活動在屏幕是不可見(後台進程)。決定是否終結進程,取決於運行在進程中的組件狀態。關於組件的狀態,將在後面一篇——組件生命周期中介紹。

2、線程

雖然你可能會將你的應用程序限制在一個進程中,但有時候你會需要衍生一個線程做一些後台工作。因為用戶界面必須很快地響應用戶的操作,所以活動寄宿的線程不應該做一些耗時的操作如網路下載。任何不可能在短時間完成的操作應該分配到別的線程。

線程在代碼中是用標準的Java線程對象創建的,Android提供了一些方便的類來管理線程——Looper用於在線程中運行消息循環、Handler用戶處理消息、HandlerThread用戶設置一個消息循環的線程。

Looper類

該類用戶在線程中運行消息循環。線程默認沒有消息循環,可以在線程中調用prepare()創建一個運行循環;然後調用loop()處理消息直到循環結束。大部分消息循環交互是通過Handler類。下面是一個典型的執行一個Looper線程的例子,分別使用prepare()和loop()創建一個初始的Handler與Looper交互:

2.1、遠程過程調用(Remote procere calls,RPCs)

Android有一個輕量級的遠程過程調用機制——方法在本地調用卻在遠程(另外一個進程中)執行,結果返回給調用者。這需要將方法調用和它伴隨的數據分解為操作系統能夠理解的層次,從本地進程和地址空間傳輸到遠程進程和地址空間,並重新組裝調用。返回值以相反方向傳輸。Android提供了做這些工作的所有代碼,這樣我們可以專注於定義和執行RPC介面本身。

一個RPC介面僅包含方法。所有的方法同步地執行(本地方法阻塞直到遠程方法執行完成),即使是沒有返回值。簡言之,該機制工作原理如下:首先,你用簡單的IDL(interface definition language,介面定義語言)聲明一個你想實現的RPC介面。從這個聲明中,aidl工具生成一個Java介面定義,提供給本地和遠程進程。它包含兩個內部類,如下圖所示:

內部類有管理你用IDL定義的介面的遠程過程調用所需要的所有代碼。這兩個內部類都實現了IBinder介面。其中之一就是在本地由系統內部使用,你寫代碼可以忽略它。另外一個是Stub,擴展自Binder類。除了用於有效地IPC(interprocess communication)調用的內部代碼,內部類在RPC介面聲明中還包含方法聲明。你可以定義Stub的子類實現這些方法,如圖中所示。

通常情況下,遠程過程有一個服務管理(因為服務能通知系統關於進程和它連接的其它進程的信息)。它有由aidl工具生成的介面文件和Stub子類實現的RPC方法。服務的客戶端僅有由aidl工具生成的介面文件。

下面介紹服務如何與它的客戶端建立連接:

· 服務的客戶端(在本地端的)應該實現onServiceConnected() 和onServiceDisconnected() 方法,因此當與遠程服務建立連接成功和斷開連接是會通知它。然後調用bindService() 建立連接。

· 服務的onBind()方法將實現為接受或拒絕連接,者取決於它接受到的意圖(該意圖傳送到binServive())。如果連接被接受,它返回一個Stub子類的實例。

· 如果服務接受連接,Android調用客戶端的onServiceConnected()方法且傳遞給它一個IBinder對象,返回由服務管理的Stub子類的一個代理。通過代理,客戶端可以調用遠程服務。

這里只是簡單地描述,省略了一些RPC機制的細節。你可以查閱相關資料或繼續關注Android開發之旅,後面將為你奉上。

2.2、線程安全方法

在一些情況下,你實現的方法可能會被不止一個線程調用,因此必須寫成線程安全的。這對遠程調用方法是正確的——如上一節討論的RPC機制。當從IBinder進程中調用一個IBinder對象中實現的一個方法,這個方法在調用者的線程中執行。然而,當從別的進程中調用,方法將在Android維護的IBinder進程中的線程池中選擇一個執行,它不在進程的主線程中執行。例如,一個服務的onBind()方法在服務進程的主線程中被調用,在onBind()返回的對象中執行的方法(例如,實現RPC方法的Stub子類)將在線程池中被調用。由於服務可以有一個以上的客戶端,所以同時可以有一個以上的線程在執行同一個IBinder方法。因此,IBinder的方法必須是線程安全的。

同樣,一個內容提供者可以接受其它進程產生的數據請求。雖然ContentResolver 和 ContentProvider 類隱藏進程通信如何管理的,對應哪些請求的ContentResolver 方法——query()、insert()、delete()、update()、getType(),在內容提供者的進程的線程池中被調用,而不是在這一進程的主線程中。因為這些方法可以同時從任意數量的線程中調用,他們也必須實現為線程安全的。

熱點內容
tf2為什麼連接伺服器很慢 發布:2024-10-21 11:26:47 瀏覽:628
c語言有向圖 發布:2024-10-21 11:21:02 瀏覽:497
pc端國際服伺服器ip 發布:2024-10-21 11:00:44 瀏覽:695
c語言程序設計李鳳霞 發布:2024-10-21 11:00:29 瀏覽:453
如何解決伺服器過剩問題 發布:2024-10-21 10:58:13 瀏覽:327
c語言必看 發布:2024-10-21 10:44:00 瀏覽:775
家用投影儀該如何選擇配置 發布:2024-10-21 10:44:00 瀏覽:723
yumphp目錄 發布:2024-10-21 10:40:41 瀏覽:200
android文件管理器 發布:2024-10-21 10:38:45 瀏覽:797
北汽威旺有哪些配置 發布:2024-10-21 10:32:35 瀏覽:155