HandlerThread要记得quit哦

560 阅读3分钟

背景

最近在分析线程 pthread_create OOM 问题时,无意发现HandlerThread使用不当会造成一些性能损耗,可以说是加深了对 HandlerThread的理解吧

省流:不quit 线程资源无法释放,除非用来做应用层级的 例如后台任务

HandlerThread简介

HandlerThread 属于老生常谈的问题了,它本质上一个自带Loop消息循环的Thread,就是个线程 image.png

有时候我们自己也希望有个类似主线程类似的消息队列帮助我们处理消息,它就是做这个事情的。 跟主线程有着异曲同工之妙,唯一的区别就是 主线程loop队列不能退出,它是随时创建随时关闭退出。 奥妙就在下面红框的2个代码中,网上文章多如牛毛,这里就不赘述了 image.png

不quit的后果

先说结论:线程资源无法释放

通常我们会搞一个线程池工具类,然后收敛线程池统一管理,但是handlerthread 往往不受这个限制,大家使用的比较野的话,往往会有一点性能损耗

在Android中,创建一个线程会占用一定的系统资源。每个线程都需要一定的内存来存储线程的上下文信息(几百k~1M)、栈空间等。因此,创建大量的线程可能会导致内存消耗过高,从而影响应用程序的性能和稳定性。 以下是一些创建线程可能消耗的资源:

  1. 内存:每个线程都需要一定的内存来存储线程的上下文信息、栈空间和其他相关数据。如果同时创建大量的线程,会占用大量的内存资源,可能导致内存不足或内存泄漏。
  2. CPU 时间片:每个线程在执行时都需要分配CPU时间片。如果创建过多的线程,并且它们同时需要执行大量的计算或任务,可能会导致CPU过度占用,造成性能下降和响应延迟。
  3. 系统调度开销:线程的创建和销毁都需要涉及系统的调度和管理。如果频繁创建和销毁线程,会增加系统的调度开销,降低系统的效率。

不过呢,这里也不好类似线程池一样 统一搞个handlerthread,这样会让一些高优任务调度的比较慢,按需使用正常销毁就好,但是有时候必须得做点后台任务那就没办法了只能牺牲一些性能了

一些细节

我们在创建handlerthread时候 会传入一个名称,这个其实就是handlerthread 内部的线程名称,这个在我们分析cpu 线程时候比较有帮助,看个profile的截图就知道了 image.png

最后再提下 pthread_create OOM

  1. 32 位地址空间雪上加霜

对于32位的系统,当进程的逻辑地址空间不够的时候也会产生OOM,每个线程通常需要mapp 1MB左右的stack空间(如果是 native 线程,还可以通过 pthread_attr_t 参数为创建的线程指定栈的大小),32为系统进程逻辑地址4GB,用户空间少于3GB。逻辑地址空间不够(已用逻辑空间地址可以查看/proc/pid/status中的VmPeak/VmSize记录),此时创建线程产生的OOM具有如下信息

pthread_create (1040KB stack) failed: Try again

32位机 在海外东南亚那边还蛮常见的

  1. 厂商限制线程数

这些手机的线程数限制都很小,每个进程只允许最大同时开500个线程 OOM信息有以下关键字

pthread_create (1040KB stack) failed: Out of memory

言简意赅水一篇

快看,可能是东半球最好的Android面试资料