Android多进程
进程和线程
- 进程:是运行中的程序,资源分配的单元,进程拥有的资源多,进程间的切换代价大
- 线程:是进程内部的一个执行序列,是cpu的基本调度单位,拥有资源小,切换代价小,多个线程共享进程的资源
使用多进程通信场景
- 需要向其他应用获取数据
- 某些应用模块需要单独运行在进程中(WebView优化,后台进程)
- 加大一个应用可使用的内存(获取多份内存空间)
多进程原理和产生的问题
Android为每个进程分配一个虚拟机,每个进程具有独立的内存地址空间,多个进程访问同一个类会产生多个副本,这样不同进程修改同一个类的静态成员互不干扰。会产生以下问题:
- 静态成员和单例模式失效
- 线程同步机制失效
- sharedPreference机制可靠性降低
- Application会多次创建
进程优先级
ActivityManagerService掌控了所有应用进程的创建。 所有应用程序的进程都是由ActivityManagerService通过socket发送请求给Zygote进程,然后由zygote fork创建的。并且ActivityManagerService中对于每一个运行中的进程都有一个ProcessRecord对象与之对应,在ProcessRecord中,详细记录了进程中应用组件(四大组件)的相关信息,这些组件的状态就是其所在进程优先级的决定性因素。
- 前台进程:与用户交互的Activity,与用户交互Activity绑定的Service,调用startForeground方法的Service,正在执行onReceive的BroadcastReceiver,正在执行生命周期方法的Service
- 可见进程:执行onPaused的可见Activity,与可见Activity绑定的Service
- 服务进程:除了前台和可见Service的其他Service
- 后台进程:持有不可见Activity的进程,内存不足时会按照Lru测量回收。
- 空进程:不持有任何活动组件的进程,这种进程就是为了缓存,以便下次启动该进程的组件时能更快响应。
两种序列化
- Serializable:java提供接口,需要指定serialVersionUID,并且注意静态变量不属于对象不参与序列化,transient关键字标识的成员变量也不参与序列化。
- Parcelable:Android提供接口,是进行内存序列化,效率高(Serialzable是IO读写,序列化到磁盘,基于java反射,序列化会产生大量变量,引发高频GC)
内存序列化选择Parcelable,存储到设备或网络存储则用Serializable。
Android的IPC方式
使用Bundle+Intent实现IPC
在intent中传递序列化数据,但只支持Bundle支持的数据。一般用于四大组件通信。
使用文件共享
在一个进程中先序列化信息到文件中,然后在另一个进程中反序列化出来,但是并发读写可能导致内容不是最新的。不适合高并发,无法做到进程即时通信。
使用Messager
它对AIDL进行了封装,可通过它在不同进程中传递Message对象(内含数据),并且它一次只处理一个请求,所以不需要考虑线程同步。适用于低并发一对多即时通信,不支持RPC,也只支持传输Bundle支持的数据
使用AIDL
Messager只有传递消息,若要实现跨进程调用服务端方法,则要用AIDL。使用较复杂,需要处理好线程同步,支持一对多通信,支持RPC
使用ContentProvider
底层同样也是Binder,专门用于不同应用间共享数据。支持一对多进程数据共享
使用Socket
支持字节流传输,跨设备通信。适用于网络数据交换
参考