安卓线程学习五 之 HelloWorld app运行时线程资源分析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/rambomatrix/article/details/81512838

一 抛出问题

一个最普通的 HelloWorld app运行以后,总共会开启多少线程,这些线程分别是什么作用,线程的status是什么?

二 分析

helloworld app运行以后,打开Android Studio — Tools — Android — Android Device Monitor ,查看Threads信息,如图所示:
helloworldthread.png

总共有14个线程

2.1.虚拟机线程

Jit thread pool worker thread 0

Signal Catcher

用来接收、处理进程收到的SIGQUIT、SIGUSR1信号。当收到SIGQUIT即 signal 3时,signal catcher 会调用HandleSignalQuit函数来进行一些信息的Dump。如果是native层代码crash,Signal Catcher则捕获不到,需要

JDWP

java 平台调试体系结构的缩写,通过 JPDA 提供的 API,开发人员可以方便灵活的搭建 Java 调试应用程序

ReferenceQueueDaemon

FinalizerWatchdogDaemon

FinalizerDaemon

HeapTaskDaemon

引用自老罗的分析https://blog.csdn.net/luoshengyang/article/details/42555483
1. ReferenceQueueDaemon:引用队列守护线程。我们知道,在创建引用对象的时候,可以关联一个队列。当被引用对象引用的对象被GC回收的时候,被引用对象就会被加入到其创建时关联的队列去。这个加入队列的操作就是由ReferenceQueueDaemon守护线程来完成的。这样应用程序就可以知道那些被引用对象引用的对象已经被回收了。
2. FinalizerDaemon:析构守护线程。对于重写了成员函数finalize的对象,它们被GC决定回收时,并没有马上被回收,而是被放入到一个队列中,等待FinalizerDaemon守护线程去调用它们的成员函数finalize,然后再被回收。
3. FinalizerWatchdogDaemon:析构监护守护线程。用来监控FinalizerDaemon线程的执行。一旦检测那些重定了成员函数finalize的对象在执行成员函数finalize时超出一定的时候,那么就会退出VM。
4. HeapTrimmerDaemon:堆裁剪守护线程。用来执行裁剪堆的操作,也就是用来将那些空闲的堆内存归还给系统。

2.2.Binder线程

Binder:10221_1

Binder:10221_2

Binder:10221_3

在android系统中,每个app进程在启动之后会创建一个binder线程池,用于响应ipc客户端的请求。例如:app与AMS等服务之间可以通过IPC双向通信,当app作为服务端的时候,就需要通过binder线程响应来自AMS的请求。一个Server进程有一个最大Binder线程数限制,默认为16个binder线程。

2.3.app业务线程

main线程

应用启动时,系统会为应用创建一个名为“主线程”的执行线程。 此线程非常重要,因为它负责将事件分派给相应的用户界面小部件,其中包括绘图事件。 此外,*它也是应用与* Android UI 工具包组件(来自 android.widget 和 android.view 软件包的组件)进行交互的线程。因此,主线程有时也称为 UI 线程。参考文档

RenderThread 渲染线程

Android 5.0之后新增加的一个线程,用来协助UI线程进行图形绘制。所有的GL命令执行都放到这个线程上。渲染线程在RenderNode中存有渲染帧的所有信息,并监听VSync信号,因此可以独立做一些属性动画,这样即便主线程block也可以保证动画流畅

摘自老罗的分析:

Render Thread在运行时主要是做以下两件事情:
1. 执行Task Queue的任务,这些Task一般就是由MainThread发送过来的,例如,MainThread通过发送一个DrawFrameTask给RenderThread的TaskQueue中,请求RenderThread渲染窗口的下一帧。
2. 执行PendingRegistrationFrameCallbacks列表的IFrameCallback回调接口。每一个IFrameCallback回调接口代表的是一个动画帧,这些动画帧被同步到Vsync信号到来由RenderThread自动执行。具体来说,就是每当Vsync信号到来时,就将一个类型为DispatchFrameCallbacks的Task添加到RenderThread的TaskQueue去等待调度。一旦该Task被调度,就可以在RenderThread中执行注册在PendingRegistrationFrameCallbacks列表中的IFrameCallback回调接口了。

hwuiTask1

Android3.0以前,图形绘制是由Skia完成,Skia是一个向量绘图库,使用CPU来进行运算;从Android3.0 开始,Google用hwui取代了Skia,由于Opengl的支持不完全,有少量图形api仍由Skia完成,多数view的绘制通过HWUI模块使用openGL的函数来实现。

三 总结

上面看到的线程构成了一个app运行所需要的基本线程框架。包括了art虚拟机对应的四个守护线程;用于Ipc通信的binder线程;用于硬件加速的渲染线程和图形绘制的ui线程。

除此之外,在app业务开发过程会大量写一些work线程,比如AsyncTask、HandlerThread、新建线程池等。线程的合理使用可以提高升序的健壮性和性能、线程使用不正确会引起线程死锁、线程不安全、线程频繁新建销毁导致性能低下等问题。因此下一步,需要继续学习线程安全、线程通信等知识。先提前思考下面的线程使用规则:

  1. UI线程是非线程安全,view绘制需要将消息发送给UI线程进行处理。
  2. UI线程不可以用来处理耗时操作,比如网络通信、数据库操作、binder耗时接口操作、jni操作等
  3. 集合类在使用过程需要注意线程安全,以hashmap为例,这是非线程安全的,如果不注意多线程安全问题,可能会发生
    死锁的问题。

猜你喜欢

转载自blog.csdn.net/rambomatrix/article/details/81512838
今日推荐