Android 进程和线程详解

转载至:http://blog.chinaunix.net/uid-29694663-id-4329910.html


当启动一个应用程序组件时,如果该应用没有正在运行的其它程序组件,那么Android系统将为这个应用创建一个新进程(包含一个线程)用于运行应用。缺省情况下,一个应用的所有组件(Activity,Service等)运行在同一个进程和线程中(称为“主”线程)。如果在启动一个应用程序组件时,这个应用已经有进程在运行(因为有应用的其它组件存在),那么这个应用程序组件将使用同一进程和线程运行。当然你可以使用不同进程来运行不同的组件,或者在进程中创建新的线程。


进程

缺省情况,应用的所有组件都运行在同一个进程,而且应用不应该改变这个传统。然而,如果你发现你需要控制某个组件运行在那个进程中,你可以通过应用程序清单来配置。

在应用程序清单文件中,每个类型的应用程序组件-<activity>,<service>,<receiver>和<provider>都支持 android:process 属性,这个属性用来指明该程序组件运行的进程。你可以为应用程序组件设置这个属性以使每个组件运行在不同的进程中或者某几个组件使用同一进程。你也可以通过设置android:process 使得不同应用中的组件运行在同一个进程中-前提是这些应用使用同一个Linux用户名并且使用同一个证书签名。

<Application>元素也支持 android: process 属性,用来为应用程序的所有组件设置缺省的进程。

Android系统中系统资源过低而且有需要为用户立即提供服务的进程需要启动时可能会终止某些进程的运行。运行在这些被终止的进程中的程序组件将逐个被销毁。此后如果还有工作需要这些应用程序组件时将启动新的进程。

系统中决定哪些进程可以杀死时,系统将权衡这些进程对用户的重要性。比如,对于那些运行不可见的Activity的进程比运行屏幕上可见的Activity的进程更容易被杀死。


进程生命周期

Android系统会尽可能长的保持应用程序进程的运行,但总会有需要清除旧的进程来释放资源以满足新或是重要的进程的运行。为了决定哪些进程可以杀死,哪些进程需要保留,系统根据运行在其中的应用程序组件和这些组件的状态,将这些进程分配到“重要性层次表”中。具有最低重要性的进程首先被杀死,次重要性的进程为其次等等直到系统恢复所需的资源。

“重要性层次表”可以分为五个层次,下面列表给出了不同类型的进程的重要性等级(最重要的排在前面):

1.前台进程

这种进程是当前用户所需要的。一个进程被认为是前台进程需满足下面条件之一:

  1. ·        本进程中有Service和当前用户有交互Activity的绑定。
  2. ·        本进程中有Service正在执行某个生命周期回调函数(onCreate(),onStart()或onDestroy())。
  3. · 本进程含有一个虽然不在前台但却部分可见的Activity(该Activity的onPause()被调用)。可能发生的情形是前台Activity显示一对话框,此时之前的Activity变为部分可见。
  4. public void onClick(View v) {
  5.         public void run() {
  6.                         mImageView.setImageBitmap(b);

  7.                         // TODO Auto-generated method stub
  8.                 }
  9. }
复制代码


    乍一看,这段代码应该很好的完成工作,因为它创建了一个新线程来完成网络操作。然而它违法了上面说的第二个规则:不要在非UI线程中操作UI组件。在这段代码中的工作线程中而不是在UI线程中,直接修改ImageView,这将导致一些不可以预见的后果,常常导致发现此类错误捕捉异常困难和费时。

为了更正此类错误,Android提供了多种方法使得在非UI线程中访问UI组件,下面给出了其中的几种方法:

  1. public void onClick(View v) {
  2.         public void run() {
  3.             mImageView.post(new Runnable() {
  4.                     mImageView.setImageBitmap(bitmap);
  5.             });
  6.     }).start();
  7. public void onClick(View v) {
  8. }
  9. private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
  10.       * delivers it the parameters given to AsyncTask.execute() */
  11.         return loadImageFromNetwork(urls[0]);
  12.     
  13.       * the result from doInBackground() */
  14.         mImageView.setImageBitmap(result);
  15. }
复制代码


    现在UI是安全的而且代码变的更简单,因为它把在工作线程中的工作和在UI线程的工作很好的分隔开。

你应该参考AsyncTask的详细文档以便更好的理解它的工作原理,这里给出它的基本步骤:

  1. <li font-size:12px;line-height:1.8em;"="" style="word-wrap: break-word; margin: 0px 0px 0px 2em; padding: 0px 0px 0px 10px; list-style: decimal-leading-zero outside; font-family: Monaco, Consolas, '';">· 你可以使用generics为Task指定参数类型,返回值类型等
复制代码


要注意的是,由于系统配置的变化(比如屏幕的方向转动)你的工作线程可能会碰到意外的重新启动,这种情况下,你的工作线程可能被销毁,你可以参考Android开发包中Shelves示例来处理线程重新的问题。


编写“线程安全”方法

在某些情况下,你编写的方法可能会被多个线程调用,此时你实现方法时要保证它是“线程安全”的。

“线程安全”是可以被远程调用方法实现的基本规则—比如支持“绑定”的Service中的方法。当在实现IBinder接口同一进程中调用IBinder对象的方法时,该方法运行在调用者运行的同一线程中。然而,如果调用来自不同进程,系统将使用和实现IBinder接口的进程关联的线程池中的某个线程(非该进程中的UI线程)来执行IBinder的方法。比如,一个Service的onBind()方法会在某个Service进程的UI线程中调用,而由onBind()返回的对象(比如实现远程调用RPC方法的子类)的方法会在线程池的某个线程中执行。由于Service可能服务于多个客户端,那么可能有线程池中的多个线程同时执行IBinder对象的某个方法,因此IBinder对象的方法必须保证是线程安全的。

同样的,一个Content Provider可以接受来自其它多个进程的数据请求。http://wnsrylc88.biz尽管ContentResolver和ContentProvider类隐藏了处理这些数据请求时进程间通信的详细机制,这些请求方法有query(), insert (), delete (), update () 及getType() 等。这些方法会在Content Provider的进程的线程池的某个线程中执行。由于这些方法同时有不定数量的线程同时调用,因此这些方法也必须是线程安全的。


进程间通信

    Android系统支持使用远程调用(RPC)来实现进程间通信(IPC)的机制。此时在一个Activity或其它程序组件调用某个方法,而该方法的实现执行是在另外的进程中(远程进程)。远程调用可能给调用者返回结果。这就要求将方法调用和相关数据分离到某个层次,以便能让操作系统理解,能从本地进程传送数据到远程进程地址空间,在远程能够重新构造数据以执行方法,返回数据也能够反向返回。Android支持能够完成这些进程间通信事务的所有代码,从而使你可以只关注于定义和实现远程调用的接口。

    为了使用进程间通信(IPC),你的应用需要使用bindService()绑定到某个Service。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值