Android进程基础知识

最近项目中需要接入一个SDK,这个SDK会开启一个新进程,但是它自身的初始化要在app的主进程中进行。由于对进程的理解不够,导致我在此坑中挣扎了整整一个礼拜,痛定思痛,终于下定决心研究一下进程。


1. 什么是进程

进程占有一定的资源空间,内部资源共享,一个进程至少包含一个线程。但是线程没有独立的内存空间,而是在它所在的进程中资源共享。也正是这个原因,有时候我们需要考虑到线程安全的问题,避免在不同线程中对同一个资源文件进行操作导致的冲突。

在安卓中,一个应用启动时会新建一个进程,该进程由zgoate进程fork出来,具体过程参照Android的系统启动流程和应用启动流程这篇文章。

2.进程与线程的区别

线程(Thread)、进程(Process)这俩货中文翻译都有一个“程”字,但是不代表二者有很多的共同点。我举一个例子,大家就明白了。

如果把CPU比作一座工厂,内存比作工厂的占地面积,那么,进程就是工厂的车间,线程就是车间里的工人。那么,他们之间的对应关系如下:

  • 多个车间可以同时运行,但是受限于工厂的占地面积:代表CPU可以实现多进程,但是受限于内存容量的大小。
  • 单个车间面积有限制:Android下单个进程所占内存大小的限制。
  • 车间与车间之间需要通过卡车来运输货物:多进程通信的载体Binder.
  • 一个车间至少有一个工人:一个进程中至少包含一个线程。
  • 车间里的空间是共享的,每个工人都可以使用这些空间:进程的内存空间是共享的,每个线程都可以使用这些内存。
  • 车间的卫生间每次只能一个人进去,其他人也想挤进去,就会吵架:当线程使用某些内存时,其他线程必须等它结束才能使用这块内存,否则会线程不安全。
  • 上卫生间的人把门锁上可以避免其他工人进入:加互斥锁可以避免多个线程同时读写某块内存区域

详细内容参照这篇文章http://blog.csdn.net/yapian8/article/details/41015631

3. 进程分类

按优先级由高到低分为5类:

进程优先级金字塔

3.1 前台进程:

用户当前操作所必需的进程。

前台进程一般是visble(可见的)但要注意,visible不一定是active的。比如activity弹出一个dialog,那么activity可见但是inactive,dialog变成active。

3.2 可见进程:

没有任何前台组件、但仍会影响用户在屏幕上所见内容的进程。
比如弹出dialog后面的activity。

3.3 服务进程:

正在运行的Service。

由于运行服务的进程其级别高于托管后台 Activity 的进程,因此启动长时间运行操作的 Activity 最好为该操作启动服务,而不是简单地创建工作线程,当操作有可能比 Activity 更加持久时尤要如此。否则,后台的Activity被销毁时,工作线程也会被销毁,导致后台操作的失败。

例如,正在将图片上传到网站的 Activity 应该启动服务来执行上传,这样一来,即使用户退出 Activity,仍可在后台继续执行上传操作。使用服务可以保证,无论 Activity 发生什么情况,该操作至少具备“服务进程”优先级。 同理,广播接收器也应使用服务,而不是简单地将耗时冗长的操作放入线程中。

3.4 后台进程:

已经调用onStop方法的activity。正如2.3中所提到的,避免因为后台进程的销毁导致后台任务的中断。

3.5 空进程:

不包含任何应用组件的进程

总之,时刻注意四大组件的生命周期,避免因为GC问题导致关键性的操作失败。

4. 为什么需要多进程

一个应用默认只有一个进程,进程名称就是包名,每个进程都有自己独立的资源和内存空间,系统给每个进程分配的内存大小是有限制的,当进程占用内存超过限制时,就会报OOM的错误。

OOM的问题的解决方法:

  • 代码优化
    比如图片处理视频播放等采用高效的内存占用少的框架
  • 向系统申请更多内存
    在AndroidManifest.xml中的application标签下添加android:largeHeap=”true”。
  • 多进程
    开启新进程的方法很简单,在四大组件的标签下添加android:process属性即可。为了便于调试,可以调试时将process属性去掉,调试完再恢复即可。

5. 进程间通信(IPC: InterProcess Communication)

因为每个进程都有自己独立的资源和内存空间,所以堆栈信息,文件操作都是独立的,这就需要用到IPC。IPC实现方式:

5.1 Activity.

通过指定Activity的action,访问其他进程的Activity,通过Intent或者Uri来传递数据。

5.2 ContentProvider

多个应用程序之间使用文件或者Sqlite共享数据,利用ContentProvider实现对数据的增删改查。

5.3 BroadCast

类似Activity,通过Intent传递数据,

5.4 Service

Service有两个作用:后台运行和跨进程通信。其中跨进程通信是通过AIDL(Android Interface Definition Language)服务实现的。

5.5 Messenger

当您需要执行 IPC 时,为您的接口使用 Messenger
要比使用 AIDL 实现它更加简单,因为 Messenger
会将所有服务调用排入队列,而纯粹的 AIDL 接口会同时向服务发送多个请求,服务随后必须应对多线程处理。
对于大多数应用,服务不需要执行多线程处理,因此使用 Messenger
可让服务一次处理一个调用。如果您的服务必须执行多线程处理,则应使用 AIDL 来定义接口。

限于篇幅不再展开,具体实现方式参考https://www.cnblogs.com/sevenyuan/archive/2013/03/22/2975122.html,有空再写一篇关于进程间通信的文章,

当然如果嫌麻烦,可以使用别人封装好的框架,比如eventBus之类。


IT文库 » Android进程基础知识
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址