Intent Service 会不会ANR

作者: 蛋黄酥酥 | 来源:发表于2017-05-19 13:21 被阅读490次

    在项目中需要在后台进行一些IO工作,为了不阻塞UI线程,所以开启了一个Intent Service执行,然而在云测试中在几个机器上遇到了ANR。很疑惑。根据Intent Service源码,它并不会阻塞UI线程。

    IntentService源码注释

    所以决定写个demo验证一下IntentService、Service、Thread与ANR的关系。

    test ANR demo

    sleep 30秒的代码实现:

     long endTime = System.currentTimeMillis() + 30 * 1000;
     while (System.currentTimeMillis() < endTime) {
          synchronized (this) {
               try {
                   wait(endTime - System.currentTimeMillis());
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
           }
    }
    

    如上图所示。写了6个代码段

    执行结果分别如下:

    1. start IntentService,在onHandleIntent中wait 30秒。无ANR
    05-19 11:01:19.009 28195-28195/com.example.testanr D/HHH: 开始执行intent service
    05-19 11:01:19.046 28195-30213/com.example.testanr D/HHH: MyIntentService --> onHandleIntent, start
    05-19 11:01:49.046 28195-30213/com.example.testanr D/HHH: MyIntentService --> onHandleIntent, end
    

    可以看出30秒后正常退出。说明在IntentService中执行耗时操作并不会导致ANR

    1. for循环开启10个IntentService,在每个的onHandleIntent中wait 30秒。无ANR
    05-19 11:02:15.107 28195-28195/com.example.testanr D/HHH: 开始执行intent service for循环10个
    05-19 11:02:15.202 28195-31060/com.example.testanr D/HHH: MyIntentService --> onHandleIntent, start
    05-19 11:02:45.202 28195-31060/com.example.testanr D/HHH: MyIntentService --> onHandleIntent, end
    05-19 11:03:45.210 28195-31060/com.example.testanr D/HHH: MyIntentService --> onHandleIntent, start
    05-19 11:04:15.210 28195-31060/com.example.testanr D/HHH: MyIntentService --> onHandleIntent, end
    ...分别顺序执行了10次
    05-19 11:11:45.253 28195-31060/com.example.testanr D/HHH: MyIntentService --> onHandleIntent, start
    05-19 11:12:15.253 28195-31060/com.example.testanr D/HHH: MyIntentService --> onHandleIntent, end
    

    结果是10组 有序的这样开始-结束 开始-结束,所以IntentService是等前面的请求结束之后再执行下一个。 这个证实了 IntentService 采用单独的线程每次只从队列中拿出一个请求进行处理

    1. start Service,在onStartCommand中wait 30秒。有ANR
    05-19 11:12:42.965 28195-28195/com.example.testanr D/HHH: 开始执行service
    05-19 11:12:42.992 28195-28195/com.example.testanr D/HHH: MyService --> onHandleIntent, start
    //20秒的时候发生ANR
    05-19 11:13:12.993 28195-28195/com.example.testanr D/HHH: MyService --> onHandleIntent, end
    

    说明Service里执行时间不能超过20秒,超过则会发生ANR

    1. start Thread,在run方法中wait 30秒。无ANR
    05-19 11:13:21.067 28195-28195/com.example.testanr D/HHH: 开始执行my thread
    05-19 11:13:21.071 28195-9066/com.example.testanr D/HHH: MyThread --> run, start: my thread
    05-19 11:13:51.071 28195-9066/com.example.testanr D/HHH: MyThread --> run, end: my thread
    

    在Tread中wait30秒,正常结束,不会ANR。

    1. for循环开启10个Thread,在每个run方法中wait 30秒。无ANR
    05-19 11:13:56.574 28195-28195/com.example.testanr D/HHH: 开始执行my thread for循环10个
    05-19 11:13:56.580 28195-9575/com.example.testanr D/HHH: MyThread --> run, start: thread3
    05-19 11:13:56.581 28195-9573/com.example.testanr D/HHH: MyThread --> run, start: thread1
    05-19 11:13:56.582 28195-9572/com.example.testanr D/HHH: MyThread --> run, start: thread0
    05-19 11:13:56.593 28195-9574/com.example.testanr D/HHH: MyThread --> run, start: thread2
    05-19 11:13:56.600 28195-9576/com.example.testanr D/HHH: MyThread --> run, start: thread4
    05-19 11:13:56.610 28195-9582/com.example.testanr D/HHH: MyThread --> run, start: thread9
    05-19 11:13:56.621 28195-9579/com.example.testanr D/HHH: MyThread --> run, start: thread6
    05-19 11:13:56.623 28195-9578/com.example.testanr D/HHH: MyThread --> run, start: thread5
    05-19 11:13:56.625 28195-9580/com.example.testanr D/HHH: MyThread --> run, start: thread7
    05-19 11:13:56.626 28195-9581/com.example.testanr D/HHH: MyThread --> run, start: thread8
    05-19 11:14:26.581 28195-9575/com.example.testanr D/HHH: MyThread --> run, end: thread3
    05-19 11:14:26.583 28195-9573/com.example.testanr D/HHH: MyThread --> run, end: thread1
    05-19 11:14:26.584 28195-9572/com.example.testanr D/HHH: MyThread --> run, end: thread0
    05-19 11:14:26.593 28195-9574/com.example.testanr D/HHH: MyThread --> run, end: thread2
    05-19 11:14:26.601 28195-9576/com.example.testanr D/HHH: MyThread --> run, end: thread4
    05-19 11:14:26.615 28195-9582/com.example.testanr D/HHH: MyThread --> run, end: thread9
    05-19 11:14:26.621 28195-9579/com.example.testanr D/HHH: MyThread --> run, end: thread6
    05-19 11:14:26.624 28195-9578/com.example.testanr D/HHH: MyThread --> run, end: thread5
    05-19 11:14:26.624 28195-9580/com.example.testanr D/HHH: MyThread --> run, end: thread7
    05-19 11:14:26.626 28195-9581/com.example.testanr D/HHH: MyThread --> run, end: thread8
    

    可以看出是无序同时开启的。

    1. for循环开启10000个Thread,在每个run方法中wait 30秒。OOM崩溃
      大约开到2000个的时候OOM崩溃了。

    通过源码可以分析出IntentService为什么可以执行耗时任务。一个IntentService,内部就创建了一个线程,通过Android提供的 Handler Message Looper,这些消息处理的类 构成了一个消息处理的模型。所以IntentService 的onHandleIntent 这个方法其实是在IntentService 中开辟的一个子线程中处理的。
    理论上IntentService里执行耗时任务不会ANR,但是如果这个任务涉及到IO或者资源之类的,会导致ANR。

    相关文章

      网友评论

        本文标题:Intent Service 会不会ANR

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