Android的程式,執行緒模型
Android 包括一個應用程式框架、幾個應用程式庫和一個基於 Dalvik 虛擬機器的執行時,所有這些都執行在 Linux 核心之上。
通過利用 Linux 核心的優勢,Android 得到了大量作業系統服務,包括程式和記憶體管理、網路堆疊、驅動程式、硬體抽象層、安全性等相關的服務。
有關Java虛擬機器跟程式,執行緒的關係請參看下面這篇文章:
程式、執行緒與JVM、CLR
http://blog.csdn.net/ghj1976/archive/2010/04/13/5481038.aspx
下面這篇文章對Android的程式和執行緒描述的很好,我在這篇文章基礎補充了一些圖片和資訊。
http://blog.csdn.net/L_serein/archive/2011/03/22/6269270.aspx
android程式模型:
在安裝Android應用程式的時候,Android會為每個程式分配一個Linux使用者ID,並設定相應的許可權,這樣其它應用程式就不能訪問此應用程式所擁有的資料和資源了。
在 Linux 中,一個使用者ID 識別一個給定使用者;在 Android 上,一個使用者ID 識別一個應用程式。
應用程式在安裝時被分配使用者 ID,應用程式在裝置上的存續期間內,使用者ID 保持不變。
預設情況下,每個apk執行在它自己的Linux程式中。當需要執行應用程式中的程式碼時,Android會啟動一個jvm,即一個新的程式來執行,因此不同的apk執行在相互隔離的環境中。
下圖顯示了:兩個 Android 應用程式,各自在其自己的基本沙箱或程式上。他們是不同的Linux user ID。
開發者也可以給兩個應用程式分配相同的linux使用者id,這樣他們就能訪問對方所擁有的資源。
為了保留系統資源,擁有相同使用者id的應用程式可以執行在同一個程式中,共享同一個jvm。
如下圖,顯示了兩個 Android 應用程式,執行在同一程式上。
不同的應用程式可以執行在相同的程式中。要實現這個功能,首先必須使用相同的私鑰簽署這些應用程式,然後必須使用 manifest 檔案給它們分配相同的 Linux 使用者 ID,這通過用相同的值/名定義 manifest 屬性 android:sharedUserId 來做到。
Android程式知識的補充:
下圖是標準的Android 架構圖,
其中我們可以看到在“Android本地庫 & Java執行環境層”中,Android 執行時中,
Dalvik是Android中的java虛擬機器,可支援同時執行多個虛擬機器例項;每個Android應用程式都在自己的程式中執行,都擁有一個獨立的Dalvik虛擬機器例項;
所有java類經過java編譯器編譯,然後通過SDK中的dx工具轉成.dex格式交由虛擬機器執行。
Android系統程式
init程式(1號程式),父程式為0號程式,執行根目錄底下的init可執行程式,是使用者空間程式
——-> /system/bin/sh
——-> /system/bin/mediaserver
——-> zygote
—————–> system_server
—————–>com.android.phone
—————–>android.process.acore(Home)
… …
kthreadd程式(2號程式),父程式為0號程式,是核心程式,其他核心程式都是直接或者間接以它為父程式
Android的單執行緒模型
當一個程式第一次啟動時,Android會同時啟動一個對應的主執行緒(Main Thread),主執行緒主要負責處理與UI相關的事件,如:使用者的按鍵事件,使用者接觸螢幕的事件以及螢幕繪圖事件,並把相關的事件分發到對應的元件進行處理。所以主執行緒通常又被叫做UI執行緒。
在開發Android 應用時必須遵守單執行緒模型的原則: Android UI操作並不是執行緒安全的並且這些操作必須在UI執行緒中執行。
如果在非UI執行緒中直接操作UI執行緒,會丟擲android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views,這與普通的java程式不同。
由於UI執行緒負責事件的監聽和繪圖,因此,必須保證UI執行緒能夠隨時響應使用者的需求,UI執行緒裡的操作應該向中斷事件那樣短小,費時的操作(如網路連線)需要另開執行緒,否則,如果UI執行緒超過5s沒有響應使用者請求,會彈出對話方塊提醒使用者終止應用程式。
如果在新開的執行緒中需要對UI進行設定,就可能違反單執行緒模型,因此android採用一種複雜的Message Queue機制保證執行緒間通訊。
Message Queue:
Message Queue是一個訊息佇列,用來存放通過Handler釋出的訊息。Android在第一次啟動程式時會預設會為UI thread建立一個關聯的訊息佇列,可以通過Looper.myQueue()得到當前執行緒的訊息佇列,用來管理程式的一些上層元件,activities,broadcast receivers 等等。你可以在自己的子執行緒中建立Handler與UI thread通訊。
通過Handler你可以釋出或者處理一個訊息或者是一個Runnable的例項。每個Handler都會與唯一的一個執行緒以及該執行緒的訊息佇列管理。
Looper扮演著一個Handler和訊息佇列之間通訊橋樑的角色。程式元件首先通過Handler把訊息傳遞給Looper,Looper把訊息放入佇列。Looper也把訊息佇列裡的訊息廣播給所有的Handler,Handler接受到訊息後呼叫handleMessage進行處理。
例項如下:
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); editText = (EditText) findViewById(R.id.weather_city_edit); Button button = (Button) findViewById(R.id.goQuery); button.setOnClickListener(this); Looper looper = Looper.myLooper(); //得到當前執行緒的Looper例項,由於當前執行緒是UI執行緒也可以通過Looper.getMainLooper()得到 messageHandler = new MessageHandler(looper); //此處甚至可以不需要設定Looper,因為 Handler預設就使用當前執行緒的Looper } public void onClick(View v) { new Thread() { public void run() { Message message = Message.obtain(); message.obj = "abc"; messageHandler.sendMessage(message); //傳送訊息 } }.start(); } Handler messageHandler = new Handler { public MessageHandler(Looper looper) { super(looper); } public void handleMessage(Message msg) { setTitle((String) msg.obj); } }
對於這個例項,當這個activity執行玩oncreate,onstart,onresume後,就監聽UI的各種事件和訊息。
當我們點選一個按鈕後,啟動一個執行緒,執行緒執行結束後,通過handler傳送一個訊息,由於這個handler屬於UI執行緒,因此這個訊息也傳送給UI執行緒,然後UI執行緒又把這個訊息給handler處理,而這個handler是UI執行緒創造的,他可以訪問UI元件,因此,就更新了頁面。
由於通過handler需要自己管理執行緒類,如果業務稍微複雜,程式碼看起來就比較混亂,因此android提供了AsyncTask類來解決此問題。
AsyncTask:
首先繼承一下此類,實現以下若干方法,
onPreExecute(), 該方法將在執行實際的後臺操作前被UI thread呼叫。可以在該方法中做一些準備工作,如在介面上顯示一個進度條。
doInBackground(Params...), 將在onPreExecute 方法執行後馬上執行,該方法執行在後臺執行緒中。這裡將主要負責執行那些很耗時的後臺計算工作。
可以呼叫publishProgress方法來更新實時的任務進度。該方法是抽象方法,子類必須實現。
onProgressUpdate(Progress...),在publishProgress方法被呼叫後,UI thread將呼叫這個方法從而在介面上展示任務的進展情況,例如通過一個進度條進行展示。
onPostExecute(Result), 在doInBackground 執行完成後,onPostExecute 方法將被UI thread呼叫,後臺的計算結果將通過該方法傳遞到UI thread.
使用時需要遵循以下規則:
1)Task的例項必須在UI thread中建立
2)execute方法必須在UI thread中呼叫
3)不要手動的呼叫這些方法,只呼叫execute即可
4)該task只能被執行一次,否則多次呼叫時將會出現異常
示例如下:
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); editText = (EditText) findViewById(R.id.weather_city_edit); Button button = (Button) findViewById(R.id.goQuery); button.setOnClickListener(this); } public void onClick(View v) { new GetWeatherTask().execute(“aaa”); } class GetWeatherTask extends AsyncTask<String, Integer, String> { protected String doInBackground(String... params) { return getWetherByCity(params[0]); } protected void onPostExecute(String result) { setTitle(result); } }
參考資料:
Android程式和執行緒模型
http://blog.csdn.net/L_serein/archive/2011/03/22/6269270.aspx
Hello Android 第三版 (二)
http://blog.csdn.net/cqwty/archive/2010/09/08/5870219.aspx
理解 Android 上的安全性
http://www.ibm.com/developerworks/cn/xml/x-androidsecurity/
相關文章
- Android程式框架:執行緒與執行緒池Android框架執行緒
- 程式和執行緒模型執行緒模型
- android程式和執行緒Android執行緒
- 瞭解 Android 的程式和執行緒Android執行緒
- Android中的多程式、多執行緒Android執行緒
- 執行緒模型執行緒模型
- Dubbo的執行緒模型執行緒模型
- Redis的執行緒模型Redis執行緒模型
- Android多執行緒之執行緒池Android執行緒
- 理解微信小程式的雙執行緒模型微信小程式執行緒模型
- Dubbo執行緒模型執行緒模型
- WPF執行緒模型執行緒模型
- redis執行緒模型Redis執行緒模型
- Android執行緒池Android執行緒
- Android中的執行緒池Android執行緒
- 走進Java Android 的執行緒世界(二)執行緒池JavaAndroid執行緒
- 多執行緒------執行緒與程式/執行緒排程/建立執行緒執行緒
- 程式執行緒篇——程式執行緒基礎執行緒
- 03.執行緒模型執行緒模型
- webrtc執行緒模型分析Web執行緒模型
- 淺談Netty的執行緒模型Netty執行緒模型
- Redis執行緒模型的前世今生Redis執行緒模型
- Android中的執行緒通訊Android執行緒
- Android JNI 中的執行緒操作Android執行緒
- Node.js 的單執行緒事件驅動模型和內建的執行緒池模型Node.js執行緒事件模型
- osi7層模型及執行緒和程式模型執行緒
- 程式-程式-執行緒執行緒
- 執行緒以及多執行緒,多程式的選擇執行緒
- [短文速讀 -5] 多執行緒程式設計引子:程式、執行緒、執行緒安全執行緒程式設計
- Android優化幀動畫過程中的多執行緒模型思考Android優化動畫執行緒模型
- 程式執行緒篇——執行緒切換(上)執行緒
- 程式執行緒篇——執行緒切換(下)執行緒
- 執行緒、執行緒與程式、ULT與KLT執行緒
- 深入學習redis 的執行緒模型Redis執行緒模型
- 多執行緒之共享模型執行緒模型
- 執行緒(一)——執行緒,執行緒池,Task概念+程式碼實踐執行緒
- 執行緒池執行模型原始碼全解析執行緒模型原始碼
- 【java】【多執行緒】程式、執行緒的基本概念(1)Java執行緒
- Android執行緒間通訊Android執行緒