欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android应用进程和线程问题解析

程序员文章站 2022-05-14 10:41:00
线程与进程的主要区别(操作层面) 进程是资源的分配和调度的一个独立单元,而线程是cpu调度的基本单元 同一个进程中可以包括多个线程,并且线程共享整个进程的资源(寄存器、堆栈、上下文),一个进行至少包...

线程与进程的主要区别(操作层面)

进程是资源的分配和调度的一个独立单元,而线程是cpu调度的基本单元

同一个进程中可以包括多个线程,并且线程共享整个进程的资源(寄存器、堆栈、上下文),一个进行至少包括一个线程。

进程的创建调用fork或者vfork,而线程的创建调用pthread_create,进程结束后它拥有的所有线程都将销毁,而线程的结束不会影响同个进程中的其他线程的结束

程中执行时一般都要进行同步和互斥,因为他们共享同一进程的所有资源

线程有自己的私有属性tcb,线程id,寄存器、硬件上下文,而进程也有自己的私有属性进程控制块pcb,这些私有属性是不被共享的,用来标示一个进程或一个线程的标志

如何理解android应用的进程

进程是一个动态的过程,每一个app的运行都是在一个独立的进程中,进程有自己独立的内存和数据空间,进程的名字就是app的packagename,这些进程都是从zygote进程fork出来的,并受ams(activitymanagerservice)管理。

默认情况下,同一app的所有均在相同的进程中运行,但也可以允许app有多个进程。在androidmanifest.xml里边给四大组件配置android:process属性,就可以让这些组件在指定的进程中运行,这些进程名字都是packagename:name这种,以区分是属于哪个app,我一般称之为辅助进程。

此外,您还可以设置android:process(即不以“:”开头,以符合包命名的格式字符串为它的值),使不同应用的组件在相同的进程中运行,但前提是这些应用共享相同的linux用户id并使用相同的证书进行签署。

一些情况下可以通过设置process,如微信的小程序就是这样设计的,这个时候要注意的是不同的进程之间的通信问题。常有些开发不知道为什么自己的application.oncreate中的代码执行了两次,如果你遇到这样的情况可以检查一下androidmanifest.xml是否给某个组件配置了android:process属性。每个进程创建后,都会启动一个主线程(looper接收消息),每个组件启动前都会先创建application实例(一个进程只创建一个)。

优先级

当系统内存不足时,android系统会选择终止掉一部份进程,回收其所占用的内存空间。 为了确定保留或终止哪些进程,系统会根据进程中正在运行的组件以及这些组件的状态,将每个进程放入“重要性层次结构”中。 必要时,系统会首先消除重要性最低的进程,然后是重要性略逊的进程,依此类推,以回收系统资源。

重要性从高到低如下所示:

前台进程

可见进程

服务进程

后台进程

空进程

其实也可以用优先级(oom_adj值)来表示这个重要性。app进程的优先级是在com.android.server.am.processlist

类里边定义的。所以当内存不足的时候,进程优先级低的(oom_adj越大的,系统进程是负数),占内存大的app进程将会被优先kill掉。

很多项目都比较“变态”,总想长期霸占内存(如消息推送),所以就有了各种进程保活的黑科技面市。黑科技我们占且不论,对于一般提高进程优先级的方法,大家还是应该了解一些。

如:

进程要运行一些组件,不要成为空进程。

远行一个service,并设置为前台运行方式(startforeground)。

androidmanifest.xml中配置persistent属性(persistent的app会被优先照顾,进程优先级设置为persistent_proc_adj=-12)

关于第2点,摘抄一段代码给大家看:

privatevoidkeepalive(){try{

notificationnotification=newnotification();

notification.flags|=notification.flag_no_clear;

notification.flags|=notification.flag_ongoing_event;

startforeground(0,notification);//设置为前台服务避免kill,android4.3及以上需要设置id为0时通知栏才不显示该通知;

}catch(throwablee){

e.printstacktrace();

}

}

在service的oncreate方法调用keepalive()即可,其实就是是欺骗系统把自己当成一个一直在通知栏的notification。不过这种方式,并不保证在所有的机型上都有效。

线程

线程是cpu调度的基本单元,一个应用都有一个主线程负责处理消息。一个应用启动后,至少会有3个线程,一个主线程(ui线程)和2个binder线程。zygote进程(apk所在的进程也是由zygote进程fork出来的)还会产生有一些daemon线程如:referencequeuedaemon、finalizerdaemon、finalizerwatchdogdaemon、heaptaskdaemon,从名字大家也可以对它们的用途猜出一二。

Android应用进程和线程问题解析

线程间可以共享资源,为了保存ui的更新不会混乱,所以更新ui控件时要求在主线程进行更新,即需要保证更新ui是线程安全的。

有时还可能被问到 ui线程是安全的吗,以及引出如何更新ui,更新ui的核心handler相关知识,还可以问哪些数据结构或操作是线程安全的(线程创建,多线程,hashmap,stringbuffer,stringbuilder)等问题。