当前位置: 首页 > news >正文

掌握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的线程不应用于处理一些诸如网络下载之类的耗时操作。所有不能在瞬间完成的任务都应安排到不同的线程中去。
线程在代码中是以标准Java Thread对象创建的。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()方法来相应这些请求,而这些方法也都是由那个内容提供者的进程中所包涵的线程池提供的,而不是进程的主线程本身。

相关文章:

  • wxPython:启动画面SplashScreen介绍
  • SQL Server 2012之初次安装
  • PHP中新建图像函数
  • NAT另类使用方式
  • Cisco IPSec ××× 设计总结
  • Opalis Integration Server 安装指南
  • python ---- urllib2
  • [PHP] 面向对象
  • 兼容各种浏览器的min-height
  • VMM2012应用指南之4-向VMM中添加Hyper-V主机与应用服务器
  • Hibernate中one-to-one的深入学习
  • TCP/IP详解卷一-概述
  • 常用JS图片滚动(无缝、平滑、上下左右滚动)
  • 开发人员经常会使用的15个jquery谷歌地图插件
  • HDFS写入和读取流程
  • [译]如何构建服务器端web组件,为何要构建?
  • 【391天】每日项目总结系列128(2018.03.03)
  • Angular 响应式表单 基础例子
  • DataBase in Android
  • flask接收请求并推入栈
  • idea + plantuml 画流程图
  • Python 基础起步 (十) 什么叫函数?
  • React16时代,该用什么姿势写 React ?
  • Sequelize 中文文档 v4 - Getting started - 入门
  • vue2.0开发聊天程序(四) 完整体验一次Vue开发(下)
  • Wamp集成环境 添加PHP的新版本
  • WePY 在小程序性能调优上做出的探究
  • 回流、重绘及其优化
  • 写给高年级小学生看的《Bash 指南》
  • 原生js练习题---第五课
  • 再次简单明了总结flex布局,一看就懂...
  • zabbix3.2监控linux磁盘IO
  • ​ArcGIS Pro 如何批量删除字段
  • ${factoryList }后面有空格不影响
  • (51单片机)第五章-A/D和D/A工作原理-A/D
  • (Redis使用系列) Springboot 实现Redis 同数据源动态切换db 八
  • (附源码)springboot学生选课系统 毕业设计 612555
  • (含react-draggable库以及相关BUG如何解决)固定在左上方某盒子内(如按钮)添加可拖动功能,使用react hook语法实现
  • (黑马出品_高级篇_01)SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式
  • (全注解开发)学习Spring-MVC的第三天
  • (三) diretfbrc详解
  • (十一)c52学习之旅-动态数码管
  • (状压dp)uva 10817 Headmaster's Headache
  • ****Linux下Mysql的安装和配置
  • .bat批处理出现中文乱码的情况
  • .equals()到底是什么意思?
  • .htaccess 强制https 单独排除某个目录
  • .NET C# 使用 SetWindowsHookEx 监听鼠标或键盘消息以及此方法的坑
  • .net framework 4.0中如何 输出 form 的name属性。
  • .NET 中创建支持集合初始化器的类型
  • .NET框架类在ASP.NET中的使用(2) ——QA
  • .NET中统一的存储过程调用方法(收藏)
  • @JsonFormat与@DateTimeFormat注解的使用
  • [ 网络基础篇 ] MAP 迈普交换机常用命令详解
  • [2018-01-08] Python强化周的第一天