Android:多線程之進程與線程

來源:互聯網
上載者:User

 進程與線程

  一般來說,Android中為一個應用程式開啟一個進程進行執行,在這個應用程式中的所有組件,通過單獨的線程進行執行,而其中所有的線程,共用該應用程式進程的資源。當一個應用程式啟動的時候,Android系統啟動一個新的Linux應用程式的進程和一個執行線程。預設情況下,一個應用程式運行中的所有組件運行在相同的進程和線程中,這裡的線程一般稱為主線程。如果一個應用程式的組件開始的時候,已經存在一個進程,那麼應用程式會在與它相同的執行線程中開始這個組件。

進程

  預設情況下,同一應用程式下的所有組件運行在同一進程中,大多數應用程式不應該改變這個。然而,如果需要控制那個進程屬於那個組件,可以在AndroidManifest.xml檔案中進行配置。一般來說,組件元素:<activity>、<service>、<receiver>、<provider>均支援一個android:process屬性,可以設定這個屬性讓不同的組件單獨運行在自己的進程中,也可以使用這個屬性使不同的應用程式組件運行在相同的進程中,並共用相同的Linux使用者ID和賦予同樣的認證。

  Tips:<application>元素也支援android:process屬性,用於設定所有的組件。

  Android在記憶體較低的情況下,會關閉一些優先順序較低的進程以增大記憶體運行更重要的進程,而在這個進程中的所有線程,也會被同時銷毀。在記憶體足夠的情況下,Android系統會視圖儘可能保持應用程式進程,以達到下次的啟動並執行快速啟動,但最終需要移除舊的進程,回收記憶體用於新的或更重要的進程。通過進程的優先順序來判斷是否被回收,一般會回收優先順序低的進程,以給優先順序高的進程騰出資源。

  下面是五類Android進程,他們的優先順序順序排列:

  1. Foreground process:前台進程。
  2. Visible prcess:可見進程。
  3. Service process:服務進程。
  4. Background process:後台進程。
  5. Empty process:空進程。

  Tips:一個進程的優先順序是可以變化的。

 

線程

  當應用程式啟動時,系統會建立一個執行線程在這個應用程式的的進程中,一般被稱為“主線程”。這個線程是非常重要的,因為它負責把事件分發給響應的使用者組件,包括繪製事件等,因此主線程又被稱為UI線程。系統並不會為每個組件建立一個單獨的線程,而是在UI線程中,完成這些組件的初始化的,因此系統回調方法是運行在UI線程中,如click事件。

  當程式執行比較複雜的工作來應對使用者互動的時候,哪怕應用程式被正確的執行了,單線程模式也可能會導致運行效能很低下。舉例來說,如果一切的應用功能都發生在UI線程中,當執行耗時操作的時候,如訪問網路或查詢資料,均會阻塞UI先,將導致其他的事件不被分發到事件隊列中,包括螢幕繪製事件。導致從使用者的角度來看,應用程式死掉了。而在Android系統中,當UI線程被阻塞超過幾秒鐘(大約是5秒)的時候,會彈出“應用程式沒有響應”的對話方塊,造成使用者體驗差,可能會迫使使用者決定退出你的應用或者乾脆直接卸載它。

  此外,Android的UI ToolKit包下的所有組件都不是安全執行緒的,所以,不能在一個單獨的背景工作執行緒中操作這些UI組件,必須在UI線程中操作。因此,對於單執行緒模式,Android有兩個規則:

  1. 不能阻塞UI線程
  2. 不能在背景工作執行緒中訪問Android UI ToolKit包下的組件。

  對於耗時的操作,應該放在單獨的線程中。例如:下面通過一個Demo監聽按鈕點擊事件,下載一個圖片,從單獨的線程中,並顯示在一個ImageView中。

 1         btnError2.setOnClickListener(new View.OnClickListener() {             2             @Override 3             public void onClick(View v) { 4                 // 增加一個線程訪問網路 5                 new Thread(new Runnable() { 6                     @Override 7                     public void run() { 8                         // 擷取地址下的圖片 9                         Bitmap btm=loadImageFromNetwork("http://ww4.sinaimg.cn/bmiddle/786013a5jw1e7akotp4bcj20c80i3aao.jpg");10                         imageView1.setImageBitmap(btm);                        11                     }12                 }).start();13                 14             }15         });

  起初,這似乎是合理的,啟動了一個新線程來訪問網路,但是它違反了規則二,不能在Android UI主線程之外修改UI組件,而在click中new Thread的是一個背景工作執行緒,在背景工作執行緒中無法操作UI組件,以上Demo會報錯。

  要修正上面的錯誤,Android提供幾種方法可以從其他線程中訪問UI線程:

  • Activity.runOnUiThread(Runnable):運行在指定的UI線程上,如果當前線程是UI線程,那麼立即執行,如果當前線程不是UI線程,則發布到UI線程的事件隊列中。
  • View.post(Runnable):將事件發布到UI線程中,立即被執行。
  • View.postDelayed(Runnanle,long):將事件發布到UI線程中,延遲被執行,延遲數為傳遞的long參數。

  下面通過兩個Dem來通過上面介紹的方法來操作UI組件:

  Activity.runOnUiThread:

 1         btnRunOnUiThread.setOnClickListener(new View.OnClickListener() { 2              3             @Override 4             public void onClick(View v) { 5                 new Thread(new Runnable() { 6                      7                     @Override 8                     public void run() { 9                         final Bitmap btm=loadImageFromNetwork("http://ww4.sinaimg.cn/bmiddle/786013a5jw1e7akotp4bcj20c80i3aao.jpg");10                         MainActivity.this.runOnUiThread(new Runnable() {                            11                             @Override12                             public void run() {13                                 imageView1.setImageBitmap(btm);                                14                             }15                         });16                     }17                 }).start();18             }19         });

  效果示範:

   View.post

%201%20%20%20%20%20%20%20%20%20btnPost.setOnClickListener(new%20View.OnClickListener()%20{%202%20%20%20%20%20%20%20%20%20%20%20%20%20%203%20%20%20%20%20%20%20%20%20%20%20%20%20@Override%204%20%20%20%20%20%20%20%20%20%20%20%20%20public%20void%20onClick(View%20v)%20{%205%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20new%20Thread(new%20Runnable()%20{%206%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%207%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20@Override%208%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20public%20void%20run()%20{%209%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20final%20Bitmap%20btm=loadImageFromNetwork("http://ww1.sinaimg.cn/bmiddle/88ff29e8jw1e7pjnpfxbrj20dp0a90tb.jpg");10                         imageView1.post(new Runnable() {11                             12                             @Override13                             public void run() {14                                 // TODO Auto-generated method stub15                                 imageView1.setImageBitmap(btm);16                             }17                         });18                     }19                 }).start();                20             }21         });

  效果示範:

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.