android中线程和进程工作原理

2024-01-22 14:58

本文主要是介绍android中线程和进程工作原理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Android中默认情况下,同一应用中的所有组件运行在同一个进程和线程中。你的应用中没有其他组件在运行,那么Android将会给你开启一个新的Linux的进程,然后运行一个main线程来运行你的应用。如果你应用中已经有其他组件在运行,你再开启你的应用时,开启的应用会使用之前正在运行的线程和进程。

下面介绍一个应用中的线程和进程是如何工作的。

一、进程。

默认情况下,同一应用程序的所有组件运行在相同的进程,大多数应用程序不应该改变这种情况。然而,如果你发现你需要控制某一组件属于同一进程,你可以在manifest文件中进行实现。

在<activity>这些标签中都支持Android:process属性这样用户可以指定某些组件运行在哪一个具体的进程上。具有相同 的Linux 用户ID并且在相同的证书下开发的不同应用中的组件可以运行在相同的进程中。通过上述的熟悉就可以实现。

<application>也支持该属性,给应用设置默认的运行的进程。

1.进程的声明周期。当系统资源紧张或者内存使用量较高的时候,Android会选取当前的一些进程予以关闭,进而提高你的设备的运行性能。Android中主要有5中级别的进程。

1)前台进程。下面五种情况说明是前台进程。在一个给定的时间内前台进程的数量是很少的,其基本不会被系统关闭。

(1)用户正在与其交互(调用onResume方法重新开始)。

(2)一个绑定到Activity的Service,并且用户正在于其进行交互。

(3)一个Service但是调用了startForeground方法。

(4)一个调用onCreate onStart onDestory的Service回调方法。

(5)一个Broadcast Receiver正在调用onReceive方法。

2)可见进程。

不是前台进程但是对用户当前可见的界面还是有影响的进程。

(1)一个Activity调用了onPause方法。

(2)一个绑定了可见或者前台进程的Service。

3)服务进程。

      调用了startService的Service,但是没有绑定到可见和前台进程上。当内存过低的时候,服务可能会被停掉来保证可见和前台进程的正常运行。

4)后台进程。

     对用户当前没有任何的响应,可以随时关闭的进程。系统中会存在大量的后台进程,并且使用LRU算法对这些进程进行维护来提高系统的运行效率。当Activity中调用onstop方法,进程就成为了后台进程。

5)空进程。

    空进程不会持有任何活动应用的组件,空进程存在的目的是为了缓存,以提高下次组件启动的速度。操作系统会对进程的缓存和内核内部的缓存进行衡量,是系统运行最优。

上述,优先级从高到底,主要是按照进程的重要程度进行分类的。

二、线程。

当一个应用开启的时候,操作系统会为应用创建一个main线程来运行应用。这个线程非常重要,其负责管理将所有的事件派发到适当的用户接口工具中,包括drawable事件。该线程并负责与Android UI工具包中的组件进行交互,所以该线程又被称为UI线程。同一个组件的实例将会运行在相同的线程中,运行在系统进程中的组件都是由同一个UI线程实例化的。故所有的响应系统的回调函数如onKeyDown都会运行在进程中的UI线程中。UI线程还需要负责和UI工具包进行交互。

这里以点击Button从新绘制当前View为例进行说明;

       当用户点击一次Button按钮时,你应用的UI线程会将你的点击事件派发到widget,widget反过来会设置按压状态然后发送一个invalidate事件到事件队列,你的UI线程随后将从事件队列中取出事件,然后通知widget需要重新绘制当前View。

       当你的应用要执行用户交互敏感的操作的时候,如网络访问,数据库查询,其操作可能会很耗时,很可以能导致ANR,这时会给用户很差的使用体验。并且UI工具包是不安全的,你需要使用worker线程对UI进行维护,并且你需要维护其和UI线程交互的所有操作。下面有两条建议:

(1)不要阻塞UI线程。否则事件将不会派发,然后就出现了ANR。

(2)不要再UI线程之外访问AndroidUI工具包。

故,关键不要阻塞UI线程。对于耗时的线程可以放到其他的线程中进行处理。如下面的操作

public void onClick(View v) {new Thread(new Runnable() {public void run() {Bitmap b = loadImageFromNetwork("http://example.com/image.png");mImageView.setImageBitmap(b);}}).start();
}
但是,这违背了第(2)条准则。Android提供了下面的三种方式来解决上述问题。

  • Activity.runOnUiThread(Runnable)
  • View.post(Runnable)
  • View.postDelayed(Runnable, long)
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();
}
上述代码完成了网络请求操作和主线程的分离,并且将对UI工具包的访问又放到了main线程中进行。

但是,随着操作的复杂上述代码是不太好维护的。可以在worker Thread中使用Handler对来自UI线程中的消息进行派发。但是,或许最好的方式就是进程AsynTask类,能够简化Worker Thread和UI之间的交互。

AsynTask的使用方式:

public void onClick(View v) {new DownloadImageTask().execute("http://example.com/image.png");
}private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {/** The system calls this to perform work in a worker thread and* delivers it the parameters given to AsyncTask.execute() */protected Bitmap doInBackground(String... urls) {return loadImageFromNetwork(urls[0]);}/** The system calls this to perform work in the UI thread and delivers* the result from doInBackground() */protected void onPostExecute(Bitmap result) {mImageView.setImageBitmap(result);}
}
使用上述方式,你的代码的安全性就比较高了,因为其将两个线程分离开。

AsynTask使用综述:

1)可以使用泛型来指定参数类型,进度值和最终值。

2)doInBackground会在Worker Thread中自动调用。而onPostExecute onPreExecute  onProgessUpdate会自动的在UI线程中调用。

3)doInbackgroudn的返回值会发送到哦你PostExecute方法。

4)你可以在doInbackground方法中任意的调用publishProgess方法来执行UI线程中的onProgessUdapte方法。

3)你可以在任何线程中,在任何时间取消该任务。


但是如果在运行期间发生了,运行时配置改变的时候,你的Worker Thread可能会被中断的。



IPC简介

Android中提供了一种远程过程调用(RPC)的机制用来处理IPC过程。RPC机制中,当一个Activity或者应用程序的其他的组件调用了RPC中的方法,该方法会在别的进程(远端进程)中执行然后将返回值返回给调用者。这就需要将方法调用和数据分解到一个操作系统可以理解的水平,并且能够将其从本地进程和地址空间中传递到远程的进程和地址空间,然后再重新组装和定制调用。返回值会以相反的方向传递返回给本地。Android中已经提供了实现IPC的所有的代码,因此程序员只需要关注和实现RPC编程接口。

如果想要使用IPC,那么你的应用必须要绑定到Service上,即调用bi



翻译自:Android官方文档。


这篇关于android中线程和进程工作原理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/633330

相关文章

Golang HashMap实现原理解析

《GolangHashMap实现原理解析》HashMap是一种基于哈希表实现的键值对存储结构,它通过哈希函数将键映射到数组的索引位置,支持高效的插入、查找和删除操作,:本文主要介绍GolangH... 目录HashMap是一种基于哈希表实现的键值对存储结构,它通过哈希函数将键映射到数组的索引位置,支持

Python如何精准判断某个进程是否在运行

《Python如何精准判断某个进程是否在运行》这篇文章主要为大家详细介绍了Python如何精准判断某个进程是否在运行,本文为大家整理了3种方法并进行了对比,有需要的小伙伴可以跟随小编一起学习一下... 目录一、为什么需要判断进程是否存在二、方法1:用psutil库(推荐)三、方法2:用os.system调用

Android实现在线预览office文档的示例详解

《Android实现在线预览office文档的示例详解》在移动端展示在线Office文档(如Word、Excel、PPT)是一项常见需求,这篇文章为大家重点介绍了两种方案的实现方法,希望对大家有一定的... 目录一、项目概述二、相关技术知识三、实现思路3.1 方案一:WebView + Office Onl

Android实现两台手机屏幕共享和远程控制功能

《Android实现两台手机屏幕共享和远程控制功能》在远程协助、在线教学、技术支持等多种场景下,实时获得另一部移动设备的屏幕画面,并对其进行操作,具有极高的应用价值,本项目旨在实现两台Android手... 目录一、项目概述二、相关知识2.1 MediaProjection API2.2 Socket 网络

Java程序进程起来了但是不打印日志的原因分析

《Java程序进程起来了但是不打印日志的原因分析》:本文主要介绍Java程序进程起来了但是不打印日志的原因分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java程序进程起来了但是不打印日志的原因1、日志配置问题2、日志文件权限问题3、日志文件路径问题4、程序

Android实现悬浮按钮功能

《Android实现悬浮按钮功能》在很多场景中,我们希望在应用或系统任意界面上都能看到一个小的“悬浮按钮”(FloatingButton),用来快速启动工具、展示未读信息或快捷操作,所以本文给大家介绍... 目录一、项目概述二、相关技术知识三、实现思路四、整合代码4.1 Java 代码(MainActivi

Android Mainline基础简介

《AndroidMainline基础简介》AndroidMainline是通过模块化更新Android核心组件的框架,可能提高安全性,本文给大家介绍AndroidMainline基础简介,感兴趣的朋... 目录关键要点什么是 android Mainline?Android Mainline 的工作原理关键

Spring Boot循环依赖原理、解决方案与最佳实践(全解析)

《SpringBoot循环依赖原理、解决方案与最佳实践(全解析)》循环依赖指两个或多个Bean相互直接或间接引用,形成闭环依赖关系,:本文主要介绍SpringBoot循环依赖原理、解决方案与最... 目录一、循环依赖的本质与危害1.1 什么是循环依赖?1.2 核心危害二、Spring的三级缓存机制2.1 三

C#中async await异步关键字用法和异步的底层原理全解析

《C#中asyncawait异步关键字用法和异步的底层原理全解析》:本文主要介绍C#中asyncawait异步关键字用法和异步的底层原理全解析,本文给大家介绍的非常详细,对大家的学习或工作具有一... 目录C#异步编程一、异步编程基础二、异步方法的工作原理三、代码示例四、编译后的底层实现五、总结C#异步编程

如何解决idea的Module:‘:app‘platform‘android-32‘not found.问题

《如何解决idea的Module:‘:app‘platform‘android-32‘notfound.问题》:本文主要介绍如何解决idea的Module:‘:app‘platform‘andr... 目录idea的Module:‘:app‘pwww.chinasem.cnlatform‘android-32