Android-多进程初识

Android-多进程初识

学习自

《Android开发艺术探索》
https://baike.baidu.com/item/%E8%BF%9B%E7%A8%8B/382503?fr=aladdin#1
https://blog.csdn.net/cmyperson/article/details/56278433

进程与线程

IPC(Inter-Process Communication)指的是进程间通信,指的是两个进程之间交换数据的过程。在学习IPC之前我们得先了解一下什么是进程,什么是线程。

进程是应用程序的实例,是操作系统进行资源分配和调度的最小单元,每个进程都代表着应用的一个实例

线程是程序执行的最小单元,线程本身是不占有资源的(除了维持本身的资源除外),线程与进程贡献资源。

一个进程最少包括一个线程(UI线程),但是如果在UI线程中执行大量耗时的操作的话,那么就会造成UI无响应。当然这是不可取的。

采用多进程的好处

虽然使用了多进程以后在数据通信方面变的比较繁杂并且可能会遇到各种各样的问题,但是多进程也有自己的好处。众所周知Android的每个应用程序可以调用的内存是有限制的,但是如果分配的内存不够我们的应用程序的话,那么我们就可以通过多进程的方式来获取更多的内存资源。

还有如果我们的应用程序如果需要一些独立的模块的话,也需要采用多进程。

Dalvik 虚拟机

Android系统为每个进程都单独的分配了一个 Dalvik 不同的虚拟机在内存有不同的内存空间。在不同的进程之间访问相同的类的对象,会创建不同的 副本 。这些副本之间相互独立,互不干涉。这也是为何如果我们想在多进程的模式在两个不同的进程之间通过内存来共享数据,显然是不会成功的。如果想要在进程间通信就必须要用到IPC技术。

开启多进程

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="top.littledavid.studyipc">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".SecondActivity"
            android:process=":remote" />
        <activity
            android:name=".ThirdActivity"
            android:process="top.littledavid.studyipc.remote" />
    </application>

</manifest>

四大组件都可以运行在不同的进程中,通过 process 属性在 manifest 文件中为四大组件指定进程即可。
调用Activity

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        this.startActivity(android.content.Intent(this, SecondActivity::class.java))
    }
}
class SecondActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_second)
        startActivity(Intent(this, ThirdActivity::class.java))
    }
}

在上面的三个Activity中MainActivity没有指定进程,那么MainActivity采用的就是默认进程,默认进程的命名就是程序的 包名 ,如果想要修改默认进程,请给 Application 节点通过 process 属性指定进程。 SecondActivity的进程是 top.littledavid.studyipc:remote ,ThirdActivity的进程是 top.littledavid.studyipc.remote ,当在运行不同的Activity的时候就会创建不同的进程。通过ADB命名或者DDMS都可以查看已经处于运行状态的进程。

adb shell ps ##查看所有进程
### 下面的进程是我们程序的进程
u0_a84    4022  1377  1416356 49952 SyS_epoll_ 00000000 S top.littledavid.studyipc
u0_a84    4039  1377  1415804 49424 SyS_epoll_ 00000000 S top.littledavid.studyipc:remote
u0_a84    4056  1377  1418396 50172 SyS_epoll_ 00000000 S top.littledavid.studyipc.remote

上面就是我们开启的进程。其中 top.littledavid.studyipc 是我们的默认进程,而其余的两个则使我们新创建的进程。其中除了默认的进程之外,剩下的两个进程在声明的时候也不相同,一个是 :remote 一个是 <包名>.remote 。其中 : 有两个作用

  1. 最明显的一个: 省略包名,是一种简写的方式 ??
  2. 表示当前进程是一个私有的进程,不同通过共享 UID 的方式让多个应用共享进程

共享进程

在上面我们提到了共享进程这一概念,众所周知Android是基于Linux系统的,Android系统在权限设置上有一下特点:

  • Android是一种多用户的Linux系统,Android的每一个应用程序都是一个不同的User
  • 默认情况下,系统会用每个应用分配一个唯一的Linux用户Id,系统为文件设置权限,只有该用户才能够访问
  • 每一个进程都有有自己的虚拟机,因此应用与应用的运行都是相互隔离的。

通过这种多用户的方式限制了每个应用只能访问与自己相关的组件,而不能访问不相关的组件,通过可以安排两个应用共享一个Linux的用户ID,在这种情况下,他们可以互相访问彼此的文件组件等信息。

验证进程间没有共享内存空间

两个Activity MainActivitySecondActivity ,SecondActivity处于另外的一个进程。通过修改一个静态的变量来验证一下我们的理论。

//将会在两个Activity中修改i变量,来验证
object ValueHolder {
    public var i = 0
}

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        ValueHolder.i = 1
        this.startActivity(android.content.Intent(this, SecondActivity::class.java))
    }
}

class SecondActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_second)
        Log.e("TAG", ValueHolder.i.toString())
        //输出 0
    }
}

在上面的代码中,我们猛一看可能会认为应该输出 1 ,但是不要忘了,SecondActivity是在另一个进程中的即在两个不同的虚拟机中,当在不同的虚拟机中访问同一个对象的时候,会产生不同的副本,这些副本之间互不影响,这也就证实了我们上面的理论。

多进程模式造成的影响

因为不同的进程会运行与不同的虚拟机导致内存不共享,会产生以下的影响:

  1. 静态成员和单例模式完全失效
  2. 线程同步完全失效
  3. SharedPreference 可靠性下降
  4. Application对象会多次创建

①和②造成的原因是一样的,因为不是同一块内存了所以线程的同步锁也就不起作用了

③是因为SharedPreference的底层是读写XMl文件,同时并发写入同一个文件可能会早成数据的丢失。

④都知道Application类代表的是应用程序的实例,所以的原因也很简单,因为系统会为每一个进程都会建立一个虚拟机,这一过程也是创建应用程序的实例并启动的过程,所以这也是为何Application会被多次创建。

总结

这一章,我们简单的了解了一下多进程的概念和多进程的影响,在下一章中,我们来学习IPC的基础。

原文地址:https://www.cnblogs.com/slyfox/p/9382569.html

时间: 2024-10-08 14:27:39

Android-多进程初识的相关文章

android 多进程 Binder AIDL Service

本文参考http://blog.csdn.net/saintswordsman/article/details/5130947 android的多进程是通过Binder来实现的,一个类,继承了Binder,那么它的对象就可以被远程的进程使用了(前提是远程进程获取了这个类的对象[对象的引用],至于如如何获得看下文),怎么使用呢?在Android中, 则采用AIDL(Android InterfaceDefinition Language:接口定义语言)方式实现,所以我们必须写后缀为.aidl的文件

Android 多进程编程 15问15答!

ps:阅读本文 需要对android 多进程编程有一定了解. 1.Android中总共有几种方式进行IPC? 答:一共有两种,一种是binder 还有一种是socket.Binder 大家用的比较多.Socket很少有人用,这里给出一个利用Socket进行ipc通信的例子. 服务端代码: 1 package com.example.administrator.socketipcdemo; 2 3 import android.app.Service; 4 import android.conte

花费2年,字数超一万最佳总结教你Android多进程,微信微博都在用

目录 前言 为什么要使用多进程? 为什么需要"跨进程通讯"? 跨进程通讯的方式有哪些? 使用AIDL实现一个多进程消息推送 实现思路 例子具体实现 知其然,知其所以然. 跨进程的回调接口 DeathRecipient 权限验证 根据不同进程,做不同的初始化工作 总结 结语 为什么要使用多进程 对于进程的概念,来到这里的都是编程修仙之人,就不再啰嗦了,相信大家倒着.跳着.躺着.各种姿势都能背出来. 相信很多同学在实际开发中,基本都不会去给app划分进程,而且,在Android中使用多进程

Android ORM——初识greenDAO 3及使用greenDAO 3前应该掌握的一些知识点(一)

引言 总所周知,SQLite--内嵌于Android中一个占用内存极小的关系型,作为我们Android存储领域中重要的一员 ,或多或少都曾接触到数据库.即使Android系统中提供了许多操作SQLite的API,但是在业务开发中还是需要手动去编写原生SQL语句,这不仅复杂.不好维护,更重要的是不高效,常常会因为SQL语句写错而增加了开发成本,于是便出现了ORM(对象关系映射)框架,简化了编写SQL语句的开发工作,其中比较著名的有GreenDao.OrmLite.Litepal等. 一.green

Android Parcel初识

先附上一个连接,这里讲的非常详细,感谢此文作者http://www.cnblogs.com/renqingping/archive/2012/10/25/Parcelable.html 用Parcelable序列化的对象例子如下,writeToParcel方法里的dest.writeXX顺序要与createFromParcel中parcel.readXX一致,类中一定要有public static final Parcelable.Creator<Phone> CREATOR,否则会抛异常 :

利用Android多进程机制来分割组件

android对于内存有一定的限制,很多手机上对内存的限制是完全不同的.我们的应用程序其实就是一个进程,这个进程是完全独立的,这个进程分配的内存是一定的,所以我们经常会遇到OOM的问题.但,你可能不知道的是,你可以指定应用程序的一些组件运行在不同的进程中,而不是那个被用于启动应用程序的. 我们需要的仅仅是这么一个属性: android:process 该进程属性可用于activities.services.content providers和broadcast receivers 和指定的进程中

android之初识Intent

首先修改values\strings.xml文件 代码如下: <resources> <string name="app_name">mytab</string> <string name="menu_settings">Settings</string> <string name="app_title">Intent操作</string> <string

Android开发中怎样用多进程、用多进程的好处、多进程的缺陷、解决方法(转)

转自:http://blog.csdn.net/spencer_hale/article/details/54968092 1.怎样用多进程 Android多进程概念:一般情况下,一个应用程序就是一个进程,这个进程名称就是应用程序包名.我们知道进程是系统分配资源和调度的基本单位,所以每个进程都有自己独立的 资源和内存空间,别的进程是不能任意访问其他进程的内存和资源的. 如何让自己的应用拥有多个进程: 四大组件在AndroidManifest文件中注册的时候,有个属性android:process

Android进程间通信详细介绍

1.为什么需要多个进程? 默认情况下,一个Android应用中所有的组件都会运行在以包名为进程名的单个进程中,但是由于Android自身平台的一些限制或者多进程固有的一些好处,导致很多应用在实现的时候不得不选择多进程的实现方式: 1.1. Android系统对每一个应用进程的内存占用有限制,视具体设备的情况,我的测试机的单个应用的内存限制为128M,比较大了,早期的Android设备由于总的内存大小限制,对单个应用的内存限制的比较小24M或者更小.所以如果应用需要占用很大的内存,可以考虑将一些组

[书目20160624]Android应用开发从入门到精通

卢海东 著 第1章 揭开神秘面纱——Android系统简介 1   1.1 认识Android系统 2   1.1.1 Android成长历程 2   1.1.2 发行版本 3   1.1.3 得到大家的认可——Android系统的市场份额 3   1.2 Android架构解析 4   1.2.1 Android系统架构图 4   1.2.2 应用程序(Applications) 5   1.2.3 应用程序框架层(Framework) 6   1.2.4 系统运行库(Libraries) 7