android里的进程和线程

来源:互联网 发布:多肉植物 淘宝客 编辑:程序博客网 时间:2024/05/29 17:52

Android的组件运行在各自的进程里,系统会为每个进程创建UI线程,负责事件的分发,UI组件的创建,界面的重绘等工作,同时Android实现UI线程为不安全的,不能在非UI线程里操作在UI线程里创建的UI组件。同时,进程的优先级影响着系统对进程的管理,因此,理解Android进程和线程是十分必要的

进程

默认情况下,当一个应用程序没有任何组件运行时,程序处于未运行状态,此时当这个程序的某个组件启动时,系统为这个应用程序会创建一个带有单个执行线程的进程。默认情况下,所有的应用程序组件都运行在同一个进程的同一个线程里,这个线程叫主线程。一旦这个应用程序有组件处于运行状态,后续创建的组件都会运行在这个进程的主线程里。但是,程序员可以安排应用程序里的不同组件运行在不同的进程里,同时也可以为不同的进程创建不同的线程

通过在清单文件的组件节点里甚至android:process属性,可以为组件设置不同的进程,甚至可以为不同程序的不同组件分配相同的process属性,让不同程序的的组件运行在相同的进程里,但前提是这些应用程序有相同的certificates

系统在某些时候会根据进程的相对重要性kill掉某些进程,而权衡重要性主要根据进程中运行的组件以及组件的状态。

进程的生命周期

根据进程的优先等级由高到低,进程可以分为以下五个等级

前台进程(Foreground process)

前台进程包含以下任何一种组件: 1. 处于前台的activity 2. 绑定到前台activity的service 3. 正在执行 onCreate(), onStart(), or onDestroy().方法的service 4. 调用startForeground()而处于前台的service 5. 执行onReceive()方法的 BroadcastReceiver

在任何时候只存在一个前台的进程,这个进程就是在很用户进行交互的进程。通常系统不会杀掉这个进程,当时当系统处于内存页抖动状态是,为了维持UI的响应,系统也会杀掉这个进程

可见进程(Visible process)

可见进程里运行着这样的组件: 1. 处于可见暂停状态的activity(可见activity) 2. 绑定到可见或前台activity的service

服务进程(Service process)

服务进程里运行着采用started Service。

后台进程(Background process)

运行着处于后台的activity。即调用了onStop方法。

空进程(Empty process)

当进程里不含有任何组件时,该进程变为空进程,注意,当所有组件被销毁,进程以及线程一般不会立刻销毁,而是被标为空进程,由系统统一回收,另外,空进程也用作进程的缓冲,缩短进程创建的时间。

系统一般会尽可能久的保留一个进程,知道它不得已的时候才销毁进程。而销毁进程的依据是进程的优先级,优先级低的最先被销毁。系统判断进程优先级的依据是进程中运行 的组件以及组件所处的状态。如果进程中含有多种组件,系统会取最高的优先级作为进程的优先级,同时,如果A进程为B进程提供服务,A进程的优先级至少不会比B进程的优先级低

线程

Android系统默认为每个应用创建一个进程,并为这个进程创建一个主线程,由主线程负责UI组件的创建、事件的传递、视图的重绘以及系统调用的执行。这就是android的单线程模型。同时,为了保持流畅度,Android将主线程设计为线程不安全的,所以不能够在工作线程里直接操作在主线程里创建的UI组件,而应该让主线程自己操作它里面的UI组件。另外,如果在UI线程里执行耗时和阻塞操作,当主线程被阻塞超过5秒,就会出现ANR对话框。因此,Android的单线程有一下两条原则: 1. 不要在主线程意外的线程里操作主线程里的UI组件 2. 不要在主线程里执行耗时和阻塞操作。

工作线程

先来看看这样的一个示例: `public void onClick(View v) {

new Thread(new Runnable() {    public void run() {        Bitmap b = loadImageFromNetwork("http://example.com/image.png");        mImageView.setImageBitmap(b);    }}).start();

}`

这示例看上去没什么问题,但是违反了Android单线程模型原则的第二条,在子线程中操作UI会导致某种未定义和不可预期的后果,因为Android的主线程是线程不安全的,

为了解决主线程不安全的问题,Android规定,只能由主线程操作UI组件,并提供以下操作UI的方式

Activity.runOnUiThread(Runnable)View.post(Runnable)View.postDelayed(Runnable, long)

以上这些方法虽然解决了主线程不安全的问题,但是它使UI的处理操作过于分散在子线程里,这样,随着代码量的增长,不利于代码的后期维护。为了解决这个问题,可以使用Handler机制和AsyncTask解决这个问题。Handler机制和AsyncTask以后再谈。

线程安全方法

Android在实现contentProvider和Serice的时候,contentProvider和IBinder里面的方法都是执行在contentProvider和Service所在的进程里的线程池里的,不同的调用运行在不同的线程里,从而使线程安全的。

进程间通讯

Android通过远程过程调用的形式实现进程间通讯机制。通常在activity或者其他组件里调用某个方法,但是这个方法却执行在其他的进程里,然后将结果返回给它的调用者。这需要将方法调用和数据分解到系统可以理解的地步,然后把分解的数据从本地进程和地址空间传递到远程进程和它的地址空间,并在远程进程和地址空间进程组装并执行,再将结果沿相反的方向返回。Android通过底层的Binder机制已经实现好跨进程间的拆装和组装,Android程序员只需要在此基础上,实现RPC的接口即可。而Android将这种机制实现为bindService。

0 0