2020-02-02 进程间通信IPC

一、进程与线程区别

  • 进程:系统进行资源分配和调度的基本单位,进程是线程的容器

    • 进程的生命周期:
      • 前台进程
      • 可见进程
      • 服务进程
      • 后台进程
      • 空进程
  • 线程:CPU调度的最小单位。线程是进程中可独立执行的最小单位,也是 CPU 资源(时间片)调度的基本单位。同一个进程中的线程可以共享进程中的资源,如内存空间和文件句柄

    • 线程的生命周期
      • 新建:当程序使用new关键字创建了一个线程之后,该线程就处于新建状态,此时仅由JVM为其分配内存,并初始化其成员变量的值
      • 就绪:当线程对象调用了start()方法之后,该线程处于就绪状态。JVM会为其创建方法调用栈和程序计数器,等待调度运行
      • 运行:如果处于就绪状态的线程获得了CPU,开始执行run()方法的线程执行体,则该线程处于运行状态
      • 阻塞 : 当处于运行状态的线程失去所占用资源之后,便进入阻塞状态
      • 死亡:线程会以如下3种方式结束,结束后就处于死亡状态
        • run()或call()方法执行完成,线程正常结束。
        • 线程抛出一个未捕获的Exception或Error。
        • 直接调用该线程stop()方法来结束该线程——该方法容易导致死锁,通常不推荐使用

二、开启多进程方法

1、Android中的多进程模式:

  • 在Android中多进程是指一个应用中存在多个进程的情况,实现方法就是给四大组件在AndroidManifest中指定android:process属性。
  • android:process=":remote"代表当前的完整包名加上:remote进程,
    ":"开头的进程属于当前应用的私有进程,其他的应用组件不可以和它跑在同一个进程中.
    而进程名不以冒号开头的进程(android:process="com.ryg.chapter_2.remote"),属于全局进程,其他应用通过ShareUID方式可以和它跑在同一个进程中。
  • 不同进程的组件会拥有独立的虚拟机,Application以及内存空间

2、实现跨进程的通信方式:

  • Intent来传递数据

  • 共享文件和SharedPreferences

  • 基于Binder的Messenger和AIDL以及Socket等

三、IPC基础概念介绍

  • 序列化:序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化,Serializable和Parcelable接口可以完成对象的序列化的过程,当我们需要通过Intent和Binder传输数据的时候,就需要进行序列化。

  • 序列化方式:

    • 实现Serializable接口(空实现,标志接口):

      • 需要一个类实现Serializable接口,并声明一个serialVersionUID(不是必须的,它是用来反序列化的,序列化的时候系统会把当前类的serialVersionUID写入序列化的文件中,当反序列化的时候,系统回去检测文件中的serialVersionUID,如果一致,则可以实现反序列化,否则不能实现反序列化)。

      • 序列化:(将文字写入文件)

          User user = new User(0,"jake",true);
          ObjectOutputStream out = new ObjectOutputStream(new     FileOutputStrean("cache.txt");
          out.writeObject(user);
          out.close();
        
      • 反序列化(读出文件)

        ObjectInputStream in = new ObjectInputStream(new FileOInputStrean("cache.txt");
          User newUser = (User)in.readObject();
          out.close();
        
      • 静态成员变量属于类,而不属于对象,所以不会参加序列化的过程。并且使用了transient标记的成员变量也不会参与序列化。

  • 实现Parcelable接口:需要一个类实现Parcelable接口,并生成一些方法

    • 序列化功能是由writeToParcel方法来完成的,最终通过Parcel中的一系列write方法来完成的。
    • 反序列化的功能是由CREATOR来完成的,其内容标明了如何创建序列化对象和数组,并通过Parcel的一系列read方法来完成反序列化的过程。
    • 内容描述是通过describeContents来完成的。
  • Serializable和Parcelable接口的区别

    • Serializable是Java的序列化接口,使用起来开销很大,因为其序列化过程和反序列化的过程需要大量的IO操作。
    • Parcelable是Android提供的一个序列化方式,缺点就是有点麻烦,但是可以通过插件生成。并且其效率高,主要用在内存的序列化上。
  • Binder(从Framework的角度来说,Binder是ServiceManager连接各种(ActivityManager,WindowManager等)和ManagerSerice的桥梁

    • 在Android中,Binder主要用在Service,包括AIDL和Messager.在项目中创建一个aidl文件,其核心是其生成的Java文件的内部Stub和Stub的内部代理类Proxy,系统会默认生成一个这样的java文件(这个类主要分为两部分,首先它本身是一个Binder的接口(继承了IInterface,所有在Binder中传输的接口都需要继承自IInterface的接口),其次它的内部是Stub类。
    • Binder中有两个比较重要的方法(linkToDeath和unlinkToDeath),Binder运行在服务端进程,如果服务端进程由于某种原因异常终止,这个时候我们到服务端的Binder链接断裂(称为Binder死亡),会导致我们的远程调用失败,客户端的功能就会收到影响。linkToDeath是一个Binder死亡代理,当Binder死亡的时候,就会收到通知,从而解决上面的问题。

四、Android中的IPC方式

1、Bundle(只支持Bundle支持的数据类型,适用于四大组件的通信)

  • 实现了Parcelable接口,所以这个可以在不同的进程间传输,可以在Bundle中附加我们需要传输给远程进程的信息并通过Intent发送出去。

2、使用文件共享(不适合高并发,读写需要上锁)

  • A进程把数据写入文件,B进程通过读取这个文件来获取数据。但是并发的读/写会造成较大的问题。
  • SharePreference:是Android提供的轻量级存储方案,本质是xml文件,通过键值对形式存储数据。但是不建议在进程之间通信的时候使用SharePreference,其对于读/写有一定的缓存策略(内存中会有一份SharePrefernce的缓存),很大几率会造成数据丢失

3、使用Messenger(串行通信,不支持高并发)

  • 信使,底层实现方案是AIDL。在Messager中进行数据传递必须将数据放入Message中新建一个Handler,拿到message后做相关操作。Messager是以串行的方式来处理的,不适合并发.

4、使用AIDL(使用比较复杂,但是功能强大)

  • 支持的数据类型有基本数据类型,String,CharSequence,ArrayList,HashMap,Parcelable对象
  • 注意不要在onServiceConnectioned和onServiceDisconnected中进行耗时的操作。

5、使用ContentProvider(主要用于CURD)

  • 底层的实现是Binder.自定义Provider就是继承自Provider,并实现其中的onCreate(运行在主线程),query,getType,insert,delete,update等方法(运行在Binder线程池中),其增删改查是多线程并发进行的,在运用的时候需要做到多线程同步问题。

6、Socket:(主要用于网络传输)

  • 套接字,不仅能实现进程间通信,还能实现设备间通信。
  • 流式套接字TCP:面向连接,提供稳定的双向通信功能,连接的建立需要经过3次握手,画质清晰
  • 用户数据报套接字UDP:面向无连接,提供不稳定的单项功能。具有更好的效率,但是不能保证数据的正确性,流畅

你可能感兴趣的:(2020-02-02 进程间通信IPC)