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

相关文章

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

hdu4407(容斥原理)

题意:给一串数字1,2,......n,两个操作:1、修改第k个数字,2、查询区间[l,r]中与n互质的数之和。 解题思路:咱一看,像线段树,但是如果用线段树做,那么每个区间一定要记录所有的素因子,这样会超内存。然后我就做不来了。后来看了题解,原来是用容斥原理来做的。还记得这道题目吗?求区间[1,r]中与p互质的数的个数,如果不会的话就先去做那题吧。现在这题是求区间[l,r]中与n互质的数的和

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

[Linux]:进程(下)

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ 🎈🎈养成好习惯,先赞后看哦~🎈🎈 所属专栏:Linux学习 贝蒂的主页:Betty’s blog 1. 进程终止 1.1 进程退出的场景 进程退出只有以下三种情况: 代码运行完毕,结果正确。代码运行完毕,结果不正确。代码异常终止(进程崩溃)。 1.2 进程退出码 在编程中,我们通常认为main函数是代码的入口,但实际上它只是用户级

android-opencv-jni

//------------------start opencv--------------------@Override public void onResume(){ super.onResume(); //通过OpenCV引擎服务加载并初始化OpenCV类库,所谓OpenCV引擎服务即是 //OpenCV_2.4.3.2_Manager_2.4_*.apk程序包,存

hdu4407容斥原理

题意: 有一个元素为 1~n 的数列{An},有2种操作(1000次): 1、求某段区间 [a,b] 中与 p 互质的数的和。 2、将数列中某个位置元素的值改变。 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.Inpu

hdu4059容斥原理

求1-n中与n互质的数的4次方之和 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWrit

从状态管理到性能优化:全面解析 Android Compose

文章目录 引言一、Android Compose基本概念1.1 什么是Android Compose?1.2 Compose的优势1.3 如何在项目中使用Compose 二、Compose中的状态管理2.1 状态管理的重要性2.2 Compose中的状态和数据流2.3 使用State和MutableState处理状态2.4 通过ViewModel进行状态管理 三、Compose中的列表和滚动

工作常用指令与快捷键

Git提交代码 git fetch  git add .  git commit -m “desc”  git pull  git push Git查看当前分支 git symbolic-ref --short -q HEAD Git创建新的分支并切换 git checkout -b XXXXXXXXXXXXXX git push origin XXXXXXXXXXXXXX