Android中的进程和线程

进程和线程是现代网络操作系统的核心概念。Android作为一种优秀的、承袭Linux的移动操作系统,其进程和线程的概念是开发者和安全工作人员需要深入了解的问题。本文将详细介绍Android中的进程、线程以及相关的技术问题。

进程和线程的基本概念

当一个应用程序开始运行它的第一个组件时,Android会为它启动一个Linux进程,并在其中执行一个单一的线程。默认情况下,应用程序所有的组件均在这个进程的这个线程中运行。然而,你也可以安排组件在其他进程中运行,而且可以为任意进程衍生出其它线程。

Android中的进程

组件运行所在的进程由manifest文件所控制。组件元素——<activity>, <service>, <receiver>和<provider>——都有一个 process 属性来指定组件应当运行于哪个进程之内。这些属性可以设置为使每个组件运行于它自己的进程之内,或一些组件共享一个进程而其余的组件不这么做。它们也可以设置为令不同应用程序的组件在一个进程中运行——使应用程序的组成部分共享同一个Linux用户ID并赋以同样的权限。<application>元素也有一个process属性,以设定所有组件的默认值。

所有的组件实例都位于特定进程的主线程内,而对这些组件的系统调用也将由那个线程进行分发。一般不会为每个实例创建线程。因此,某些方法总是运行在进程的主线程内,这些方法包括诸如View.onKeyDown()这样报告用户动作以及生命周期通告的。这意味着组件在被系统调用的时候,不应该施行长时间的抑或阻塞的操作(诸如网络相关操作或是循环计算),因为这将阻塞同样位于这个进程的其它组件的运行。你应该如同下面线程部分所叙述的那样,为这些长时间操作衍生出一个单独的线程进行处理。

在可用内存不足而又有一个正在为用户进行服务的进程需要更多内存的时候,Android有时候可能会关闭一个进程。而在这个进程中运行着的应用程序也因此被销毁。当再次出现需要它们进行处理的工作的时候,会为这些组件重新创建进程。

在决定结束哪个进程的时候,Android会衡量它们对于用户的相对重要性。比如说,相对于一个仍有用户可见的activity的进程,它更有可能去关闭一个其activity已经不为用户所见的进程。也可以说,决定是否关闭一个进程主要依据在那个进程中运行的组件的状态。

Android中的线程

尽管你可以把你的应用程序限制于一个单独的进程中,有时,你仍然需要衍生出一个线程以处理后台任务。因为用户界面必须非常及时的对用户操作做出响应,所以,控管activity的线程不应用于处理一些诸如网络下载之类的耗时操作。所有不能在瞬间完成的任务都应安排到不同的线程中去。

线程在代码中是以标准JavaThread对象创建的。Android提供了很多便于管理线程的类:Looper用于在一个线程中运行一个消息循环,Handler用于处理消息,HandlerThread 用于使用一个消息循环启用一个线程。

RPC:远程过程调用

Android有一个轻量级的远程过程调用(RPC)机制:即在本地调用一个方法,但在远程(其它的进程中)进行处理,然后将结果返回调用者。这将方法调用及其附属的数据以系统可以理解的方式进行分离,并将其从本地进程和本地地址空间传送至远程过程和远程地址空间,并在那里重新装配并对调用做出反应。返回的结果将以相反的方向进行传递。Android提供了完成这些工作所需的所有的代码,以使你可以集中精力来实现RPC接口本身。

RPC接口可以只包括方法。即便没有返回值,所有方法仍以同步的方式执行(本地方法阻塞直至远程方法结束)。

简单的说,这套机制是这样工作的:一开始,你用简单的IDL(界面描绘语言)声明一个你想要实现的RPC接口。然后用aidl 工具为这个声明生成一个Java接口定义,这个定义必须对本地和远程进程都可见。它包含两个内部类。内部类中有管理实现了你用IDL声明的接口的远程方法调用所需要的所有代码。两个内部类均实现了IBinder接口。一个用于系统在本地内部使用,你些的代码可以忽略它;另外一个,我们称为Stub,扩展了Binder类。除了实现了IPC调用的内部代码之外,它还包括了你声明的RPC接口中的方法的声明。一般情况下,远程过程是被一个服务所管理的(因为服务可以通知系统关于进程以及它连接到别的进程的信息)。它包含着aidl工具产生的接口文件和实现了RPC方法的Stub的子类。而客户端只需要包括aidl工具产生的接口文件。

下面将说明服务与其客户端之间的连接是如何建立的,更为详细的有关RPC机制的讨论和知识,读者可以参见坦尼保姆所著的《分布式系统》一书,里面有非常详细和精彩的论述:

1) 服务的客户端(位于本地)应该实现onServiceConnected() 和onServiceDisconnected() 方法。这样,当至远程服务的连接成功建立或者断开的时候,它们会收到通知。这样它们就可以调用bindService() 来设置连接。

2) 而服务则应该实现onBind() 方法以接受或拒绝连接。这取决于它收到的intent(intent将传递给bindService())。如果接受了连接,它会返回一个Stub的子类的实例。

3) 如果服务接受了连接,Android将会调用客户端的onServiceConnected()方法,并传递给它一个IBinder对象,它是由服务所管理的Stub的子类的代理。通过这个代理,客户端可以对远程服务进行调用。

掌握线程安全方法

在一些情况下,你所实现的方法有可能会被多于一个的线程所调用,所以它们必须被写成线程安全的。

对于我们上面所讨论的RPC机制中的可以被远程调用的方法来说,这是必须首先考虑的。如果针对一个IBinder对象中实现的方法的调用源自这个IBinder对象所在的进程时,这个方法将会在调用者的线程中执行。然而,如果这个调用源自其它的进程,则这个方法将会在一个线程池中选出的线程中运行,这个线程池由Android加以管理,并与IBinder存在于同一进程内;这个方法不会在进程的主线程内执行。反过来说,一个服务的onBind() 方法应为服务进程的主线程所调用,而实现了由onBind() 返回的对象(比如说,一个实现了RPC方法的Stub的子类)的方法将为池中的线程所调用。因为服务可以拥有多于一个的客户端,而同一时间,也会有多个池中的线程调用同一个IBinder方法。因此IBinder方法必须实现为线程安全的。

类似的,一个内容提供者能接受源自其它进程的请求数据。尽管ContentResolver和ContentProvider类隐藏了交互沟通过程的管理细节,ContentProvider会由query(),insert(),delete(),update()和getType()方法来相应这些请求,而这些方法也都是由那个内容提供者的进程中所包涵的线程池提供的,而不是进程的主线程本身。

时间: 2024-08-31 20:39:18

Android中的进程和线程的相关文章

Android 中三种启用线程的方法总结

在多线程编程这块,我们经常要使用Handler(处理),Thread(线程)和Runnable这三个类,那么他们之间的关系你是否弄清楚了呢? 首先说明Android的CPU分配的最小单元是线程,Handler一般是在某个线程里创建的,因而Handler和Thread就是相互绑定的,一一对应. 而Runnable是一个接口,Thread是Runnable的子类.所以说,他俩都算一个进程. HandlerThread顾名思义就是可以处理消息循环的线程,他是一个拥有Looper的线程,可以处理消息循环

Android中杀进程的几种方法 (1) - killBackgroundProcesses

Android中杀进程的几种方法 (1) - killBackgroundProcesses ActivityManager中提供了几种方式来杀进程,比如有forceStopPackage.removeTask.killBackgroundProcesses等. 下面我们就来看看它们的背后都做了些什么. removeTask 我们之前已经写了一篇<关于Android的浅杀>来介绍这个方法的变迁,大家可以回忆一下找找感觉. 复习一下removeTask的好处是,相对后面几个,它的逻辑要简单得多.

介绍Java中关于进程与线程的相关封装类

本文主要介绍 Java 中关于进程与线程的相关封装类,揭示如何创建 Java 进程与线程,Java 封装类和实际的系统本地进程和线程是如何对应的,以及使用 Java 进程和线程的一些限制. 进程与线程,本质意义上说, 是操作系统的调度单位,可以看成是一种操作系统 "资源" .Java 作为与平台无关的编程语言,必然会对底层(操作系统)提供的功能进行进一步的封装,以平台无关的编程接口供程序员使用,进程与线程作为操作系统核心概念的一部分无疑亦是如此.在 Java 语言中,对进程和线程的封装

Android:多线程之进程与线程

 进程与线程 一般来说,Android中为一个应用程序开启一个进程进行执行,在这个应用程序中的所有组件,通过单独的线程进行执行,而其中所有的线程,共享该应用程序进程的资源.当一个应用程序启动的时候,Android系统启动一个新的Linux应用程序的进程和一个执行线程.默认情况下,一个应用程序运行中的所有组件运行在相同的进程和线程中,这里的线程一般称为主线程.如果一个应用程序的组件开始的时候,已经存在一个进程,那么应用程序会在与它相同的执行线程中开始这个组件. 进程 默认情况下,同一应用程序下的所

Java中的进程与线程的实现

概述 进程与线程,本质意义上说, 是操作系统的调度单位,可以看成是一种操作系统 "资源" .Java 作为与 平台无关的编程语言,必然会对底层(操作系统)提供的功能进行进一步的封装,以平台无关的编程接口供程序员使用,进 程与线程作为操作系统核心概念的一部分无疑亦是如此.在 Java 语言中,对进程和线程的封装,分别提供了 Process 和 Thread 相关的一些类.本文首先简单的介绍如何使用这些类来创建进程和线程,然后着重介绍这些类是如何和操作系统本 地进程线程相对应的,给出了 J

Android中线程那些事

如何理解线程 在操作系统中,线程是操作系统调度的最小单元,同时线程又是一种受限的系统资源,即线程不可能无限制的产生,并且线程的创建和销毁都会有相应的开销,当系统中存在大量的线程时,系统会通过时间陪轮转的方式调度每个线程,在这么多线程中有一个被称为主线程,主线程是指进程所拥有的线程,在JAVA中默认情况下一个进程只有一个线程,这个线程就是主线程.主线程主要处理界面交互相关的逻辑,因为用户随时会和界面发生交互,因此主线程在任何时候都必须有比较高的响应速度,否则就会产生一种界面卡顿的感觉.为了保持较高

如何在 Linux 中统计一个进程的线程数

编译自:http://ask.xmodulo.com/number-of-threads-process-linux.html作者: Dan Nanni原创:LCTT https://linux.cn/article-6240-1.html译者: strugglingyouth本文地址:https://linux.cn/article-6240-1.html 2015-9-17 10:29    收藏: 5             问题: 我正在运行一个程序,它在运行时会派生出多个线程.我想知道

《Python爬虫开发与项目实战》——1.4 进程和线程

1.4 进程和线程 在爬虫开发中,进程和线程的概念是非常重要的.提高爬虫的工作效率,打造分布式爬虫,都离不开进程和线程的身影.本节将从多进程.多线程.协程和分布式进程等四个方面,帮助大家回顾Python语言中进程和线程中的常用操作,以便在接下来的爬虫开发中灵活运用进程和线程.1.4.1 多进程 Python实现多进程的方式主要有两种,一种方法是使用os模块中的fork方法,另一种方法是使用multiprocessing模块.这两种方法的区别在于前者仅适用于Unix/Linux操作系统,对Wind

使用 Lambda 取代 Android 中的匿名类_Android

Lambda是第十一个希腊字母,大写Λ,小写λ,额,跑题了-Lambda表达式 是Java8的新特性之一: Lambda表达式 函数式接口 流API 默认方法 新的Date Time API Lambda表达式 取代了匿名类 ,取消了模板,允许用函数式风格编写代码. 由于最近接触了RxJava,遇到了Lambda,立马就喜欢上了~所以就学习了一下. 本文主要介绍一下Lambda在Android中替代匿名类的部分使用场景. 在Android中使用Lambda gradle-retrolambda