Android 频繁创建 Thread 缺点

01.遇到的问题分析

1.1 遇到的问题有哪些?

  • 继承Thread,或者实现接口Runnable来开启一个子线程,无法准确地知道线程什么时候执行完成并获得到线程执行完成后返回的结果
  • 当线程出现异常的时候,如何避免导致崩溃问题?

1.2 遇到的需求

  • 如何在实际开发中配置线程的优先级
  • 开启一个线程,是否可以监听Runnable接口中run方法操作的过程,比如监听线程的状态开始,成功,异常,完成等多种状态。
  • 开启一个线程,是否可以监听Callable接口中call()方法操作的过程,比如监听线程的状态开始,错误异常,完成等多种状态。

02.多线程实现Runnable弊端

  • 一般开启线程的操作如下所示

    1
    2
    3
    4
    5
    6
    new Thread(new Runnable() {
    @Override
    public void run() {
    //做一些任务
    }
    }).start();
  • 分析

    • 创建了一个线程并执行,它在任务结束后GC会自动回收该线程。
    • 在线程并发不多的程序中确实不错,而假如这个程序有很多地方需要开启大量线程来处理任务,那么如果还是用上述的方式去创建线程处理的话,那么将导致系统的性能表现的非常糟糕。
  • 主要的弊端有这些,可能总结并不全面

    • 大量的线程创建、执行和销毁是非常耗cpu和内存的,这样将直接影响系统的吞吐量,导致性能急剧下降,如果内存资源占用的比较多,还很可能造成OOM
    • 使用start()方法启动线程,该线程会在run()方法结束后,自动回收该线程。虽然如此,在某些场景中线程业务的处理速度完全达不到我们的要求,系统中的线程会逐渐变大,进而消耗CPU资源,大量的线程抢占宝贵的内存资源,可能还会出现OOM,即便没有出现,大量的线程回收也会个GC带来很大的压力。
    • 大量的线程的创建和销毁很容易导致GC频繁的执行,从而发生内存抖动现象,而发生了内存抖动,对于移动端来说,最大的影响就是造成界面卡顿
    • 线程的创建和销毁都需要时间,当有大量的线程创建和销毁时,那么这些时间的消耗则比较明显,将导致性能上的缺失