android 開發-Process and Thread

來源:互聯網
上載者:User

標籤:

目錄
  • 1 android中進程與線程 - Processes and Threads
    • 1.1 進程 - Processes
      • 1.1.1 進程的生命期
    • 1.2 線程 - Threads
      • 1.2.1 背景工作執行緒 - Worker threads
      • 1.2.2 使用-AsyncTask
      • 1.2.3 安全執行緒的方法 - Thread-safe methods
    • 1.3 處理序間通訊 - Interprocess Communication
android中進程與線程 - Processes and Threads

    當一個應用程式開始運行它的第一個組件時,Android會為它啟動一個Linux進程,並在其中執行一個單一的線程。預設情況下,應用程式所有的組件均在這個進程的這個線程中運行。然而,你也可以安排組件在其他進程中運行,而且可以為任意進程衍生出其它線程.
    下面將介紹如何在android系統中使用線程和進程.

進程 - Processes

    預設情況下,同一應用程式的所有組件運行在同一進程中。不過,如果你需要控制某個組件屬於哪個進程,也可以通過修改manifest檔案來實現。
    manifest檔案中的所有支援android:process屬性的那些項,例如[活動| ],[服務| ], ,和[內容提供|]都可以指定一個進程,這樣這些組件就會在指定的進程中運行.你可以設定這個屬性使每個組件運行於其自己的進程或只是其中一些組件共用一個進程.你也可以設定android:process以使不同應用的組件們可以運行於同一個進程—這樣需要這些應用共用同一個使用者ID並且有相同的數位憑證.
    元素也支援android:process屬性,用於為所有的組件指定一個預設值.
    Android系統可能在某些時刻決定關閉一個進程,比如記憶體很少了並且另一個進程更迫切的需要啟動時.進程被關閉時,其中的組件們都被銷毀.如果重新需要這些組件工作時,進程又會被建立出來。
    當決定關閉哪些線程時,Android系統會衡量進程們與使用者的緊密程度.例如,比起一個具有可見的activity的進程,那些所含activity全部不可見的進程更容易被關閉.如何決定一個進程是否被關閉,取決於進程中啟動並執行組件們的狀態.決定關閉進程的規則將在下面討論.

進程的生命期

    Android系統會盡量維持一個進程的生命,直到最終需要為新的更重要的進程騰出記憶體空間。為了決定哪個進程該終止,系統會跟據運行於進程內的組件的和組件的狀態把進程置於不同的重要性等級。當需要系統資源時,重要性等級越低的先被淘汰。
    重要性等級被分為5個檔。下面列出了不同類型的進程的重要性等級(第一個進程類型是最重要的,也是最後才會被終止的)
    1前台進程
    使用者當前正在做的事情需要這個進程。如果滿足下面的條件,一個進程就被認為是前台進程:
    1)這個進程擁有一個正在與使用者互動的Activity(這個Activity的onResume() 方法被調用)。
    2)這個進程擁有一個綁定到正在與使用者互動的activity上的Service。
    3)這個進程擁有一個前台啟動並執行Service — service調用了方法 startForeground().
    4)這個進程擁有一個正在執行其任何一個生命週期回調方法(onCreate(),onStart(), 或onDestroy())的Service。
    5)這個進程擁有正在執行其onReceive()方法的BroadcastReceiver。
    通常,在任何時間點,只有很少的前台進程存在。它們只有在達到無法調合的矛盾時才會被終止--如果記憶體太小而不能繼續運行時。通常,到了這時,裝置就達到了一個記憶體分頁調度狀態,所以需要終止一些前台進程來保證使用者介面的反應.
    2可見進程
    一個進程不擁有運行於前台的組件,但是依然能影響使用者所見。滿足下列條件時,進程即為可見:
    1)這個進程擁有一個不在前台但仍可見的Activity(它的onPause()方法被調用)。例如當一個前台activity啟動一個對話方塊時,就出了這種情況。
    2)這個進程擁有一個綁定在前台(或者可見)Activity的服務。     一個可見的進程是極其重要的,通常不會被終止,除非記憶體不夠,需要釋放記憶體以便前台進程運行。
    3服務進程
    一個進程不在上述兩種之內,但它運行著一個被startService()所啟動的service。
儘管一個服務進程不直接影響使用者所見,但是它們通常做一些使用者關心的事情(比如播放音樂或下載資料),所以除非系統沒有足夠的空間運行前台進程和可見進程時才會終止一個服務進程。
    4 後台進程
    一個進程擁有一個當前不可見的activity(activity的onStop()方法被調用)。
    這樣的進程們不會直接影響到使用者體驗,所以系統可以在任意時刻殺了它們從而為前台、可見、以及服務進程們提供儲存空間。通常有很多後台進程在運行。它們被儲存在一個LRU(最近最少使用)列表中來確保擁有最近剛被看到的activity的進程最後被殺。如果一個activity正確的實現了它的生命週期方法,並儲存了它的目前狀態,那麼殺死它的進程將不會對使用者的可視化體驗造成影響。因為當使用者返回到這個activity時,這個activity會恢複它所有的可見狀態。
    5空進程
    一個沒有任何active組件的進程。
    保留這類進程的唯一理由是快取,這樣可以提高下一次一個組件要運行它時的啟動速度。系統經常為了平衡在進程快取和底層的核心快取之間的整體系統資源而終止它們。

    跟據進程中當前活動的組件的重要性,Android會把進程按排在其可能的最進階別。例如,如果一個進程擁有一個service和一個可見的activity,進程會被定為可見進程,而不是服務進程。
    另外,如果被其它進程所依賴,一個進程的層級可能會被提高——一個服務於其它進程的進程,其層級不可能比被服務進程低。 因為擁有一個service的進程比擁有一個後台activitie的進程層級高,所以當一個activity啟動一個需長時間執行的操作時,最好是啟動一個服務,而不是簡單的建立一個背景工作執行緒。尤其是當這個操作可能比activity的生命還要長時。例如,一個向網站上傳圖片的activity,應該啟動一個service,從而使上傳操作可以在使用者離開這個activity時繼續在後台執行。使用一個service保證了這個操作至少是在"服務進程"層級,而不用管activity是否發生了什麼不幸。這同樣是廣播接收者應該使用service而不是簡單地使用一個線程的理由。

線程 - Threads

    當一個應用被啟動,系統建立一個執行線程,叫做"main"。這個線程是十分重要的,因為它主管向使用者介面控制項派發事件。其中包含繪圖事件。它也是你的應用與介面工具包(android.widget和 android.view包中的組件)互動的地方。於是main線程也被稱為介面線程。
    系統不會為每個組件的執行個體分別建立線程。所有運行於一個進程的組件都在介面線程中被執行個體化,並且系統對每個組件的調用都在這個線程中派發。因此,響應系統調用的方法(比如報告使用者動作的onKeyDown()或一個生命週期回調方法)永遠在介面線程中進程。
    例如,當使用者觸控螢幕幕上的一個按鈕時,你的應用的介面線程把觸摸事件派發給控制項,然後控制項設定它的按下狀態再向事件隊列發出一個自己介面變得無效的請求,介面線程從隊列中取出這個請求並通知這個控制項重繪它自己。
    當你的應用在響應使用者互動時需執行大量運算時,這種單線程的模式會帶來低效能,除非你能正確的最佳化你的程式。如果所有事情都在介面線程中發生,執行比如網路連接或資料庫請求這樣的耗時操作,將會阻止整個介面的響應。當線程被阻塞時,就不能派發事件了,包括繪圖事件。從使用者的角度看,程式反應太慢了。甚至更糟的是,如果介面線程被阻塞幾秒鐘(5秒左右),使用者就戶抱怨說程式沒反應了,使用者可能會退出並刪掉你的應用。
    此外,Andoid介面不是安全執行緒的。所以你絕不能在一個背景工作執行緒中操作你的介面—你只能在介面線程中管理的你的介面。所以,對於單線程模式有兩個簡單的規則:

  1. 不要阻塞介面線程
  2. 不要在介面線程之外操作介面。
背景工作執行緒 - Worker threads

    由於上述的單線程模式,不要阻塞你的介面線程以使你的應用的介面保持響應是非常重要的,那麼如果你有不能很快完成的任務,你應把它們放在另一個線程中執行(後台線程或背景工作執行緒)。

    例如,下面是的代碼是響應click事件,在另外一個線程中下載一個圖片並在一個ImageView中顯示它:

  public void onClick(View v) { new Thread(new Runnable() { public void run() { Bitmap b = loadImageFromNetwork("http://example.com/image.png"); mImageView.setImageBitmap(b); } }).start();}  


    粗略看來,這樣能很好的工作,因為它建立了一個新線程來進行網路操作。然而它違反了第二條規則:不要在介面線程之外操作介面。這段代碼在背景工作執行緒中修改了ImageView。這會導至未定義的異常出現,並且難以調試追蹤。
    為了能改正這個問題,Android提供了很多從其它線程來操作介面的方法。下面是可用的方法:

  • Activity.runOnUiThread(Runnable)
  • View.post(Runnable)
  • View.postDelayed(Runnable,long)

    例如,你可以用View.post(Runnable)來修正上面的問題:

  public void onClick(View v) { new Thread(new Runnable() { public void run() { final Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png"); mImageView.post(new Runnable() {public void run() { mImageView.setImageBitmap(bitmap); } }); } }).start(); }  

    現在這個實現終於是安全執行緒的了:網路操作在另一個線程中並且ImageView 在介面線程中改變。
    然而,由於操作複雜性的增長,這樣的代碼就變得複雜並難以維護,為了處理更複雜的互動,你可能需要線上程中用到Handler對象來處理從UI線程中傳遞的訊息。但最好的解決辦法是繼承AsyncTask類,這樣可以使得線程和UI互動這一類任務變得更輕鬆。

使用-AsyncTask

    AsyncTask可以讓程式進行非同步工作,它在一個線程中執行某些操作,之後將結果返回給UI線程。
    使用AsyncTask類時,你需要繼承AsyncTask類並實現doInBackground()回調方法。要更新UI介面,需要實現onPostExecute(),並從doInBackground()方法中獲得結果,最後,你可以在UI線程中調用execute()方法來執行操作,這樣就可以安全的更新UI介面。
    例如,我們用AsynTask來實現上面的樣本:

  public void onClick(View v) { new DownloadImageTask().execute("http://example.com/image.png");} private class DownloadImageTask extends AsyncTaskVoid, Bitmap> { protected Bitmap doInBackground(String... urls) { return loadImageFromNetwork(urls[0]); }   protected voidonPostExecute(Bitmap result) { mImageView.setImageBitmap(result); } }  

    因為AsyncTask將工作分成了兩部分,UI線程和背景工作執行緒都做自己應該做的那部分任務,因此我們就可以簡單的實現一個安全的UI更新任務了。
    更多關於AsyncTask的說明請參看AsyncTask類的參考,這裡簡單介紹下它是如何工作的:

  • AsyncTask定義了三種泛型型別 Params,Progress和Result。Params是啟動任務執行的輸入參數,比如HTTP請求的URL。Progress是背景工作執行的百分比。Result是後台執行任務最終返回的結果,比如String,Integer等。
  • doInBackground()會在背景工作執行緒中自動執行。
  • onPreExecute(), onPostExecute(), and onProgressUpdate()這三個方法都是在UI線程中調用。
  • doInBackground()方法返回的值會傳遞給onPostExecute()方法。
  • 你可以在doInBackground()方法中隨時調用publishProgress()方法以此在UI線程中更新執行進度。
  • 你可以隨時在任何線程中取消任務。

Caution: Another problem you might encounter when using a worker thread is unexpected restarts in your activity due to a runtime configuration change (such as when the user changes the screen orientation), which may destroy your worker thread. To see how you can persist your task during one of these restarts and how to properly cancel the task when the activity is destroyed, see the source code for the Shelves sample application.

安全執行緒的方法 - Thread-safe methods

    在某些情況下,你實現的方法可能會被多個線程調用,因此要保證該方法是安全執行緒的。
    一些遠程調用的方法——例如綁定服務。當我們在同一個進程中調用了某一個正在啟動並執行IBander中的方法,這個方法會運行在調用者的線程中。然而,當調用另一個進程中的方法時,該方法會在系統為這個進程開啟的線程池中的某一個線程中執行。例如,綁定服務要在UI線程中調用,onBand()返回的對象會線上程池中被調用。因為一個服務可以有多個用戶端,多個池線程可以在同一時間進行相同的IBinder方法。因此,實現IBinder方法必須是安全執行緒的。

Similarly, a content provider can receive data requests that originate in other processes. Although the ContentResolver and ContentProvider classes hide the details of how the interprocess communication is managed, ContentProvider methods that respond to those requests—the methods query(), insert(), delete(), update(), and getType()—are called from a pool of threads in the content provider‘s process, not the UI thread for the process. Because these methods might be called from any number of threads at the same time, they too must be implemented to be thread-safe.

處理序間通訊 - Interprocess Communication

    Android提供了處理序間通訊(IPC)機制,使用遠端程序呼叫(RPC),其中一個方法被稱為活動(Activity)或其他應用程式組件,但任何返回給調用者的結果都在另一個進程中執行。這就需要在系統層級從本地進程和遠程進程的地址空間中調用方法和參數,並將傳回值按相同的方法傳遞迴來。android系統能完美支援處理序間通訊(IPC),這樣你就可以專註於制定和實現RPC編程介面。
    要實現處理序間通訊(IPC),應用程式必須綁定到一個服務,使用bindService()。欲瞭解更多資訊,請參閱服務(Service)開發指南。

原文地址:http://guide.eoeandroid.com/#Processes_and_Threads 

android 開發-Process and Thread

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.