[Android] 进程(Process)和线程(Thread)

当应用的某一个组件(四大组件:Activity,Service,BroadcastReceiver,ContentProvider)启动同时应用没有其他的组件正在运行,也就是说应用的第一个组件启动的时候,安卓系统为这个应用开启一个新的Linux进程,这个进程中包含一个线程。默认情况下,一个应用的所有组件都运行在同一个进程的同一个线程下,这个线程叫主线程。但是不同的组件可以被人为地安排在不同的进程中,同时以可以为一个进程创建额外的线程。

进程



默认情况下,一个应用的所有组件都运行在同一个进程中,而且大部分应用不需要额外的进程。但是如果需要人为地控制不同的组件运行在不同的进程中,可以通过编辑manifest文件来完成这一点。

manifest文件中每一类组件<activity><service><receiver>, 和<provider>都支持android:process属性,这个属性指明这个组件运行在某一个特定的进程中。通过设置android:process,可以让每一个组件运行在自己的进程中,或者一些组件共享同一个进程而其他组件共享另一个进程。甚至可以让不同应用的组件运行在同一个进程中,当然需要这些应用有相同的Linux ID并且签名相同。

在系统内存不足并且其他应用需要内存的时候,Android系统可能会终止一些进程。运行在这些进程中的组件也会同时被摧毁。这些组件重新启动的时候进程也会重新启动。

Android系统根据进程与用户之间的关系来决定终止哪一个进程。比如说,一个进程中Activities都不对用户可见,而另一个进程中的Activity对用户可见,那么前一个进程更有可能被终止。

进程生命周期

Android系统会尽可能长时间地保持应用进程,但是系统最终需要终止一下进程以启动更重要的进程。为了决定终止哪一个进程,系统对每一个进程进行重要程度的评估与分级。最低重要程度的进程会最先被终止,然后是次低重要程度的。

进程按重要程度被分为5个层次:

1. 前台进程

与用户正在进行交互的进程,一个进程称为前台进程需要满足这些条件:

  进程拥有一个Activity,Activity正在与用户交互。(Activity的onResume()方法被调用)

  进程拥有一个Service,Service与前台Activity绑定

  进程拥有一个前台Service,Service调用了startForeground()函数

  进程拥有一个Service,Service正在执行生命周期函数

  进程拥有一个BroadcastReceiver,BroadcastReceiver正在执行onReceive()函数。

一般来说,某一时间只有少数几个前台进程存在。它们只有在非常极端的情况下才会被终止。

2.可见进程

可见进程指进程不是前台进程但是仍然能影响到用户观察到的内容。可见进程通常指下面这样的进程。

  进程拥有一个Activity,Activity不是前台Activity但是依然对用户可见(调用了onPause()但是没有调用onStop())。通常指前台Activity被一个对话框覆盖的情况

  进程拥有一个Service,Service与可见Activity绑定。

可见进程被认为是很重要的,一般不会被终止,除非一定要这样做来保证所有前台进程运行。

3.服务进程

进程拥有Service,Service调用了startService(),但是不属于前台进程和可见进程。虽然服务进程与用户界面没有直接的关系,但是它们也在做用户关心的行为,比如播放背景音乐,网络下载等。所以系统不会终止他们,除非系统没有足够的内存使得服务进程与前台进程,可见进程共存。

4.背景进程

进程拥有Activity,但是Activity对用户不可见(Activity的onStop()方法被调用)。这些进程对用户体验没有直接的影响,系统可以在任何时候终止他们来为前台进程,可见进程和服务进程提供足够的内存。通常系统中有很多背景进程,它们存贮在一个LRU(least recently used) 表中。如果Activity正确地实现了生命周期方法,终止背景进程不会对用户有任何影响。

5.空进程

不拥有任何活动的组件的进程,系统进程会终止这些进程。

Android系统对进程的评级总是按照进程能达到的最高级别。比如进程拥有一个service和一个可见Activity,这进程被评估为可见进程,而不是服务进程。

应用进程拥有Service会比拥有背景Activity获得更高的评级,所以,对于长时间的操作,Service会比Activity中创建的工作线程有优势。

线程



当应用启动时,系统为应用创建了一个执行线程,称为主线程。这个线程主要负责分发事件到合适的用户界面组件,绘制界面。主线程也是系统操作UI控件的线程,因此主线程也被称作UI线程。

系统并不会为每一个组件创造一个新的线程,所有的组件都运行在主线程中。每一个组件的系统调用在主线程中分发。因此响应系统调用的函数(比如onKeyDown()响应用户点击量后退按钮)总是运行在UI线程中。

当app执行高强度耗时长的工程时,单一的线程表现会很差。具体地说,如所有的事情都发生在UI线程中,长时间的操作比如网络连接,数据库查询将会阻塞整个UI线程。从用户的角度来看,系统似乎卡住了。更糟糕的是,如果UI线程阻塞了几秒钟(目前是大约5秒),用户会看到“application not responding"窗口。用户可能会因此推出应用。

另外,Android UI控件不是线程安全的,因此不能在其他线程中操作UI控件。所有的UI操作必须在UI线程中。因此关于Android线程两个最简单的规则是:

1.不要阻塞UI线程

2.不要在UI线程外(指其他线程)操作UI控件。

工作线程

如果需要执行长时间的行为,这些行为需要在其他的线程中执行,称作背景线程或工作线程。

比如,下面是一个例子:在工作线程中下载图片并显示在ImageView中。

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

这个代码事实上是有问题的,因为它违背了第二条规则:不要在UI线程外(指其他线程)操作UI控件。代码中在工作线程修改了ImageView的状态,这会导致不确定的行为。

为了解决这个问题,Android提供了一些在工作现在中操作UI线程的方法,比如:

比如你可以用View.post(Runnable)来修正上面的代码:

public void onClick(View v) {
    new Thread(new Runnable() {
        public void run() {
            final Bitmap bitmap =
                    loadImageFromNetwork("http://example.com/image.png");
            mImageView.post(new Runnable() {
                public void run() {
                    mImageView.setImageBitmap(bitmap);
                }
            });
        }
    }).start();
}

现在这样的实现是线程安全的了,网络操作在工作线程中完成,而ImageView在UI线程中改变。

但是,随着操作复杂度的上升,这样的代码会变得负责而且难以维护。为了处理工作线程中更复杂的行为,使用UI线程中的Handler向UI线程传递信息会是一个不错的行为,同时,使用AsyncTask或许是最好的解决方法。

时间: 2024-10-04 06:34:49

[Android] 进程(Process)和线程(Thread)的相关文章

进程(process)和线程(thread)

来源:阮一峰 进程(process)和线程(thread)是操作系统的基本概念,但是它们比较抽象,不容易掌握. 其实做一个很好的类比,就可以把它们解释地清晰易懂. 1.计算机的核心是CPU,它承担了所有的计算任务.它就像一座工厂,时刻在运行. 2.假定工厂的电力有限,一次只能供给一个车间使用.也就是说,一个车间开工的时候,其他车间都必须停工.背后的含义就是,单个CPU一次只能运行一个任务. 3.进程就好比工厂的车间,它代表CPU所能处理的单个任务.任一时刻,CPU总是运行一个进程,其他进程处于非

计算机必知必会:进程process与线程thread 进程定义为一个正在运行的程序的实例

http://www.nowamagic.net/librarys/veda/detail/1741进程和线程这对概念的理解也是很难的,至今网络上可查的资料对其的理解出入都挺大,在不同的操作系统中,如linux和windows中,其概念和实现都是有出入的.因此,我在这里结合我自己的理解谈下这两个概念,讲的都是一般性的概念,并且主要是基以WINDOWS的. 一般将进程定义为一个正在运行的程序的实例.我们在任务管理器重所看到的每一项,就可以理解为一个进程,每个进程都有一个地址空间,这个地址空间里有可

Android Framework中的线程Thread及它的threadLoop方法

当初跟踪Camera的代码中的时候一直追到了HAL层,而在Framework中的代码看见了若干个Thread.它们普遍的特点就是有一个threadLoop方法.按照字面的意思应该是这个线程能够循环处理数据.对应我想到到了java上层中的HandlerThread,这个估计也差不多,但当时心里总有一个疙瘩,想弄清楚它到底是怎么循环起来的. Android中java世界的Thread 先来看看java是怎么创建一个线程的.这个是最舒服的,也是我最熟悉的. new Thread(new Runnabl

python 进程Process模块(40)

进程Process是对各种资源管理的集合,包含对各种资源的调用.内存的管理.网络接口的调用:一个进程Process可以包含多个子进程,启动一个进程的时候会自动创建一个线程,进程里的第一个线程就是主线程(即python __name__ == ‘__main__’): 二.进程Process模块 对于线程操作可以用threading模块,那么对于进程的创建python同样也提供了Process模块,创建进程时需要导入该模块,语法如下: # 导入进程模块 from multiprocessing i

android 进程/线程管理(四)续----消息机制的思考(自定义消息机制)

继续分析handler 和looper 先看看handler的 public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } } 所以消息的处理分层三种,就是 1.传入一

Android进程与线程基本知识

Android进程与线程基本知识 本文介绍Android平台中进程与线程的基本知识. 很早的时候就想介绍一下Android中的进程和线程,但由于其他的事情一直给耽搁了,直到现在才能和大家一起分享下. 1.Android进程基本知识: 我们先来了解下Android中的进程基本知识. 当一个程序第一次启动的时候,Android会启动一个LINUX进程和一个主线程.默认的情况下,所有该程序的组件都将在该进程和线程中运行. 同时,Android会为每个应用程序分配一个单独的LINUX用户.Android

Android 进程和线程

这篇文章转载自:http://www.oschina.net/question/195301_32205 进程和线程 如果某个应用程序组件是第一次被启动,且这时应用程序也没有其他组件在运行,则Android系统会为应用程序创建一个包含单个线程的linux进程.默认情况下,同一个应用程序的所有组件都运行在同一个进程和线程里(叫做“main”主线程).如果组件启动时,已经存在应用程序的进程了(因为应用程序的其它组件已经在运行了),则此组件会在已有的进程和线程中启动运行.不过,可以指定组件运行在其他进

Android进程和线程

翻译自:https://developer.android.com/guide/components/processes-and-threads.html#Processes 一直觉得看任何书都不如看Android官方文档,权威又全面,全是干货! 进程和线程 当某个应用组件启动且该应用没有运行其他任何组件时,Android 系统会使用单个执行线程为应用启动新的 Linux 进程.默认情况下,同一应用的所有组件在相同的进程和线程(称为"主"线程)中运行. 如果某个应用组件启动且该应用已存

android 进程/线程管理(一)----消息机制的框架

一:android 进程和线程 进程是程序运行的一个实例.android通过4大主件,弱化了进程的概念,尤其是在app层面,基本不需要关系进程间的通信等问题. 但是程序的本质没有变,尤其是多任务系统,以事件为驱动的软件系统基本模式都是如下: 程序的入口一般是main: 1.初始化: 比如创建窗口,申请资源等. 2.进入while(true) 在循环中处理各种事件,直到进程退出. 四大组件是进程的部分载体,配置进程在androidmanifest.xml里面,android:process 属性.