美文网首页
Android 内存治理之线程

Android 内存治理之线程

作者: 小城哇哇 | 来源:发表于2023-07-02 15:29 被阅读0次

1、 前言

当我们在应用程序中启动一个线程的时候,也是有可能发生OOM错误的。当我们看到以下log的时候,就说明系统分配线程栈失败了。

java.lang.OutOfMemoryError: pthread_create (1040KB stack) failed: Out of memory

这种情况可能是两种原因导致的。

  • 第一个就是系统的内存不足的时候,我们去启动一个线程。
  • 第二种就是进程内运行的线程总数超过了系统的限制。

如果是内存不足的情况,需按照堆内存治理的方式来进行解决,检查应用内存泄漏问题并优化,此情况不作为本次讨论的重点。
  本次主要讨论进程内运行的线程总数超过了系统的限制所导致的情况。出现此情况时,我们就需要通过控制并发的线程总数来解决这个问题。

想要控制并发的线程数。最直接的一种方式就是利用回收的思路,也就是让我们的线程通过串行的方式来执行;一个线程执行完毕之后,再启动下一个线程。这样就能够让并发的线程总数达到一个可控的状态。
  另外一种方式就是通过复用来解决,让同一个线程的实例可以被反复的利用,只创建较少的线程实例,就能完成大量的异步操作。

2、异步任务的方式对比

对比一下,在安卓平台我们比较常用的开启异步任务的方式中,有哪些是更加有利于我们进行线程总数的控制的。

开启异步任务的方式 特点
Thread.start() 并行,难以管理
HandlerThread 带消息循环的线程,线程内部串行任务(线程复用)
AsyncTask 轻量级,串行(3.0以上),可以结合线程池使用
线程池 可管理并发数,池化复用线程
Kotlin协程 简化异步编程代码,复用线程,提高并发效率
##### 2.1 Thread

从最简单的直接创建Thread的实例的方式来说起。在Java中这种方式虽然是最简单的去开启一个线程的方式,但是在实际开发中,一旦我们通过这种方式去自己创建 Thread 类的实例,并且调用 start 来开启一个线程的话,所开启的线程会非常的难以调度和管理。这种线程也就是我们平时所说的野线程。所以我们最好不要直接的创建thread类的实例。

2.2 HandlerThread
public class HandlerThread extends Thread { }

HandlerThread是Thread类的子类,对Thread做了很多便利的封装。它有自己的Loop,它能够进行消息循环,所以就能够做到通过Handler执行异步任务,也能够做到在不同的线程之间,通过Handler进行现成的通讯。我们可以利用Handler的post操作,让我们在一个线程内部串行的执行多个异步任务。从内存的角度来说,也就相当于对线程进行了复用。

2.3 AsyncTask

AsyncTask是一个相对更加轻量级,专门为了完成执行异步任务,然后返回UI线程更新UI的操作而设计的。对于我们来说,AsyncTask更像是一个任务的概念,而不是一个线程的概念。我们不需要把它当做一个线程去理解。 AsyncTask的本质,其实也是对线程和Handler的封装。

  • Android 1.6前,串行执行,原理:一个子线程进行任务的串行执行;
  • Android 1.6到2.3,并行执行,原理:一个线程数为5的线程池并行执行,但如果前五个任务执行时间过长,会堵塞后续任务执行,故不适合大量任务并发执行;
  • Android 3.0后,串行执行,原理:全局线程池进行串行处理任务;

到了Android 3.0以上版本,默认是串行执行的,但是可以结合线程值来实现有限制的并行。也可以达到一个限制线程总数的目的。

2.4 线程池

Java语言本身也为我们提供了线程池。线程池的作用就是可以管理并发数,并且能够持续的去复用线程。如果在一个应用内部的全部异步操作,全部都采用线程池的方式来开启的话,那么我们就能够管理我们所有的异步任务了。这样一来,能够大大的降低线程治理的成本。

2.5 Kotlin协程

在Kotlin中还引入了协程的概念。协程给传统的Java的异步编程带来最大的改变,就是能够让我们更加优雅的去实现异步任务。我们前面所说的这几种异步任务的执行方式,都需要我们额外的去写大量的样本代码。而Kotlin协程就能够做到让我们用写同步代码的方式去写异步代码。

在语法的层面上,协程的另一个优势就是性能方面。协程能够帮助我们用更少的线程去执行更多的并发任务。同样也降低了我们治理内存的成本。从治理内存的角度来说,用线程池接管线程或者采用协程都是很好的方式。

相关文章

  • Android下多线程的实现

    Android下多线程相关 线程安全相关问题参考:java内存模型与线程 android下与多线程有关的主要有以下...

  • 学习笔记2-深入理解Android内核设计思想

    第5章 Android进程/线程和程序内存优化 5.1 Android 进程和线程 进程(Process)是程序的...

  • LeakCanary2.0使用及原理分析 — Kotlin重构版

    目录 前言 在写给程序员的内存泄漏治理手册中我们介绍了android内存泄漏的原理以及治理方案。通过上一节的学习我...

  • android内存泄露

    参考内存泄露从入门到精通三部曲之基础知识篇Android 内存泄漏总结Android内存泄漏研究Android内存...

  • Android内存优化1-内存原理

    要优化内存,先要弄懂android内存体系。 计算器:这是线程私有的, 标记线程执行到哪儿了。不会抛出异常 虚拟机...

  • 线程池创建和相关知识

    线程池创建(单例):Android线程池得要这么用 - 简书 线程池相关知识:Android开发之线程池使用总结 ...

  • Android 内存泄漏总结

    Android 性能相关知识 Android性能之 内存泄漏总结 Android性能之 卡顿分析解决 Androi...

  • Android内存优化之避免线程导致内存泄露

    在做Android开发过程中最长遇到的一个难点就是在Activity的生命周期中执行长时间任务而导致的不可避免的内...

  • 2017.12.27三题

    1.Android线程间通信有哪些方式? 共享变量(内存) 管道 handler机制:runOnUiThread(...

  • 高并发解决方案

    高并发之扩容思路 每个线程都有自己的工作内存,占用内存大小取决于工作内存中变量的多少与大小,随着并发的线程不断增加...

网友评论

      本文标题:Android 内存治理之线程

      本文链接:https://www.haomeiwen.com/subject/ojufudtx.html