一、进程与线程
进程:是程序运行的实例,是系统进行资源分配和调度的一个独立单位,它包括独立的地址空间,资源以及1个或多个线程。
线程:可以看成是轻量级的进程,是CPU调度和分派的基本单位。
区别
1.调度
从上面的定义可以看出一个是调度和分派的基本单位,一个是拥有资源的基本单位。2.共享地址空间,资源
进程拥有各自独立的地址空间,资源,所以共享复杂,需要用IPC,同步简单; 线程共享所属进程的资源,共享简单,但同步复杂,要通过加锁等措施。3.占用内存,cpu
进程占用内存多,切换复杂,CPU利用率低; 线程占用内存少,切换简单,CPU利用率高。4.相互影响
进程间不会相互影响; 一个线程挂掉会导致整个进程挂掉。
二、Android应用内多进程的介绍
正常情况下,一个apk启动后只会运行在一个进程中,其进程名为AndroidManifest.xml文件中指定的应用包名,所有的基本组件都会在这个进程中运行。但是如果需要将某些组件(如Service、Activity等)运行在单独的进程中,就需要用到android:process属性了。我们可以为android的基础组件指定process属性来指定它们运行在指定进程中。
好处
1、我们知道Android系统对每个应用进程的内存占用是有限制的,而且占用内存越大的进程,通常被系统杀死的可能性越大。让一个组件运行在单独的进程中,可以减少主进程所占用的内存,降低被系统杀死的概率。
2、如果子进程因为某种原因崩溃了,不会直接导致主程序的崩溃,可以降低我们程序的崩溃率。
3、即使主进程退出了,我们的子进程仍然可以继续工作,假设子进程是推送服务,在主进程退出的情况下,仍然能够保证用户可以收到推送消息。
缺陷
- 1、Application的多次重建
如果你在项目启动的时候就启动一些如百度地图的进程,你会发现Application onCreate 的打印出现了两次,而且pid的值也是不一样的。
public class MyApplication extends Application {
public static final String TAG = "viclee";
@Override
public void onCreate() {
super.onCreate();
int pid = android.os.Process.myPid();
Log.d(TAG, "MyApplication onCreate");
Log.d(TAG, "MyApplication pid is " + pid);
}
}
- 2、静态成员的失效。
设置了process属性后,产生了两个隔离的内存空间,一个内存空间里值的修改并不会影响到另外一个内存空间。所以就算是静态成员也是两个不同的成员值。
- 3、文件共享问题。
多进程情况下会出现两个进程在同一时刻访问同一个数据库文件的情况。这就可能造成资源的竞争访问,导致诸如数据库损坏、数据丢失等。在多线程的情况下我们有锁机制控制资源的共享,但是在多进程中比较难,虽然有文件锁、排队等机制,但是在Android里很难实现。解决办法就是多进程的时候不并发访问同一个文件,比如子进程涉及到操作数据库,就可以考虑调用主进程进行数据库的操作。
- 4、断点调试问题。
调试就是跟踪程序运行过程中的堆栈信息,由于每个进程都有自己独立的内存空间和各自的堆栈,无法实现在不同的进程间调试。不过可以通过下面的方式实现:调试时去掉AndroidManifest.xml中android:process标签,这样保证调试状态下是在同一进程中,堆栈信息是连贯的。待调试完成后,再将标签复原。
二、Android应用内多进程的实现
只需要添加 android:process 的属性即可,属性名可以自定义,相同的属性名的进程在同一个里面运行。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.processtest"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<application
android:name="com.example.processtest.MyApplication"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name">
<activity
android:name=".ProcessTestActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".ProcessTestService"
android:process=":remote">
</service>
</application>
</manifest>