• IPC机制总结


    IPC机制

    进程间通信

    • 进程和线程
      • 线程是CPU调度的最小单元,同时线程是一种有限的系统资源。
      • 进程一般指一个执行单元,在PC和移动设备上指一个程序或者一个应用。一个进程可以包含多个线程。
    • 多进程情况
      • 一个应用出自某些原因采用多进程模式实现,比如希望通过多进程获取多份内存空间。
      • 当前应用需要向其他应用获取数据。
      • 某些模块有运行在单独进程中的需要。
    • Android中的进程间通信方式
      • Binder实现进程间通信
      • Socket实现任意两个终端之间的通信或者一个设备上的两个进程间的通信。

    Android中的多进程模式

    • 开启多进程模式

      • 给四大组件在AndroidMenifest中指定android:process属性。
      • 非常规:通过JNI在native层去fork一个新的进程。
    • 多进程模式的运行机制

      多进程绝非仅仅是指定一个android:process属性那么简单。一般来说,使用多进程会造成以下一个方面的问题

      1. 静态成员变量和单例模式完全失效。
      2. 线程同步机制完全失效。
      3. SharedPreferences的可靠性下降。
      4. Application会多次创建。

      因为Android为每个应用/进程分配了独立的虚拟机,不同的虚拟机在内存分配上占有不同的地址空间,就导致了不同虚拟机中访问同一个对象会产生多分副本。所有运行在不同进程中的四大组件,只要通过内存来共享数据都会失败,这也是多进程带来的主要影响。

      为了解决这些问题,系统提供了很多跨进程通信方法

    IPC基础概念

    Serializable和Serializable接口都可以完成对象序列化的过程,序列化是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。

    • Serializable接口

      Java提供的一个序列化接口,在类声明中指定一个private static final long serialVersionUID(序列化后的数据中的serialVersionUID只有和当前类的相同才能够正常的被反序列化),采用ObjectInputStream和ObjectOutputStream可以实现序列化。需要注意的是:序列化恢复的对象和原对象内容完全一样,但是两者并不是同一个对象

      serialVersionUID的工作机制:序列化时系统会把当前类的serialVersionUID写入序列化文件或者其它中介中,当反序列化的时候系统又回去检测文件中的serialVersionUID,看他是否和当前类的serialVersionUID一致,如果一致就说明序列化的类的版本和当前版本是相同的,这个时候可以成功反序列化。

      另外,静态成员变量不属于类不属于对象,所以不会参与序列化过程;其次用transient关键字标记的成员变量也不参与序列化过程。

    • Parcelable接口

      实现这个接口,一个类的对象就可以通过Intent和Binder传递。 系统已经为我们提供了许多实现了Parcelable接口的类,可以直接序列化,比如Intent、Bundle、Bitmap等等,同时List和Map也可以序列化,前提是它们里面每个元素都是可以序列化的。

    Parcelable和Serializable的比较

    Serializable的作用是为了保持对象的属性到本地文件、数据库、网络流以方便数据传输,当然这种传输可以是进程内或者不同进程之间的,Serializable开销很大,在序列化和反序列化当中需要进行大量的I/O操作,效率不高。主要用于数据持久化和网络传输

    相较而言,Parcelable是Android中的序列化方式,效率很高,内存开销较小,主要用在内存序列上, 是为了在不同组件间以及不同Android应用间(AIDL)高效传输数据而设计,Parcelable是通过IBinder通信的消息的载体 。将对象序列化到存储设备或者网络传输也是可以的,但是过程较Serializable稍微复杂,而且因为Android不同版本Parcelable可能不同,所以不推荐使用Parcelable进行数据持久化。

    • Binder

      直观来说,Binder是Android中的一个类,它实现了IBinder接口。从IPC的角度看,Binder是Android中一种跨进程通信方式,BInder还可以理解为一种虚拟的物理设备,他的设备驱动是/dev/binder,该通信方式在Linux中没有;从Android Framework的角度说,Binder是ServiceManager连接各种Manager和响应ManagerService的桥梁;从Android应用层来说,Binder是客户端和服务端进行通信的媒介,当bindService的时候,服务端会返回一个包含了服务端业务调用的Binder对象,通过这个Binder对象,客户端可以获取服务端提供的服务或者数据,包括普通服务和基于AIDL的服务。

    Android中的IPC方式

    • 使用Bundle

      四大组件中的三大组件Activity、Service、Receiver都是支持在Intent中传递Bundle数据的,由于Bundle实现了Parcelable接口,可以方便地在不同的进程之间传输。

    • 使用文件共享

      由于Android系统基于Linux,使其并发读写文件可以没有限制的进行,但是也必须考虑可能出现的线程安全问题,比较适合对于数据同步要求不高的进程之间通信

      其中,对于SharedPreferences存储来说,系统对它的读写有一定的缓存策略,即在内存中会有一份SharedPreferences文件的缓存,所以再多进程模式下,系统对它的读写就变得不可靠,在并发读写时有很大几率丢失数据,因此不建议在进程间通信时使用。

    • 使用Messenger(略过)

      Messenger可以在不同进程中传递Message对象,轻松实现数据的进程间传递。使用方法很简单,对AIDL做了封装,可以很简便地进行进程间通信。

    • 使用AIDL

      • 服务端创建Service监听客户端的连接请求,然后创建AIDL文件,将暴露给客户端的接口在这个AIDL文件中声明,最后在Service中实现这个AIDL接口即可。
      • 客户端首先需要绑定服务端的Service,绑定成功后将服务端返回的Binder对象转换成为AIDL接口所属的类型,接着就可以调用AIDL中的方法了。
      • AIDL接口的创建与远程服务端Service的实现和客户端的实现、
    • 使用ContentProvider(待补充)

    • 使用Socket

      可以通过Socket来实现进程间的通信,Socket也称为“套接字”,分为流式套接字和用户数据报套接字两种,分别对应了网络传输控制层中的TCP和UDP协议。通过Socket不仅仅能够实现进程间的通信,还可以实现设备间的通信,前提是这些设备之间的IP地址互相可见。

    Binder连接池

    Binder连接池的主要作用就是将每个业务模块的Binder请求统一转发到远程Service中去执行,从而避免重复创建Service的过程,可以大大提高AIDL的开发效率。

    选择合适的IPC方式

    选择合适的IPC方式完成多进程的开发场景。

    名称 优点 缺点 适用场景
    Bundle 简单易用 只能传输Bundle支持的数据类型 四大组件间的进程间通信
    文件共享 简单易用 不适合高并发场景,并且无法做到进程间的即时通信 无并发访问情景,交换简单的数据实时性不高的场景
    AIDL 功能强大,支持一对多并发通信,支持实时通信 使用稍复杂,需要处理好线程同步 一对多通信而且有RPC(远程过程调用)需求
    Messenger 功能一般,支持一对多串行通信,支持实时通信 不能很好地处理高并发情形,不能支持RPC,数据通过Message进行传输,因此只能传输Bundle支持的数据类型 低并发的一对多即时通信,无RPC需求,或者无需要返回结果的RPC需求
    ContentProvider 在数据源访问方面功能强大,支持一对多并发数据共享,可以通过Call方法扩展其他操作 可以理解为受约束的AIDL,主要提供数据源的CRUD操作 一对多的进程间数据共享
    Socket 功能强大,可以通过网络传输字节流,支持一对多并发实时通信 实现细节稍微繁琐,不支持直接的RPC 网络数据交换
  • 相关阅读:
    47种常见的浏览器兼容性问题大汇总
    201521123029《java程序设计》第2周学习总结
    201521123029《Java程序设计》第1周学习总结
    201521123022 《Java程序设计》 第一周学习总结
    201521123020《java程序设计》第1周学习总结
    Java程序设计第三周学习总结
    201521123021第二周Java学习总结
    201521123021《Java程序设计》第1周学习总结
    201521123017 《Java程序设计》第1周学习总结
    201521123028 《Java程序设计》第2周学习总结
  • 原文地址:https://www.cnblogs.com/chen-ying/p/12259047.html
Copyright © 2020-2023  润新知