2019.5.30今日Android面试题 - 线程

线程

Android中还了解哪些方便线程切换的类?

技术点:线程通信

参考回答:对Handler进一步的封装的几个类:

  • AsyncTask:底层封装了线程池和Handler,便于执行后台任务以及在子线程中进行UI操作。
  • HandlerThread:一种具有消息循环的线程,其内部可使用Handler。
  • IntentService:是一种异步、会自动停止的服务,内部采用HandlerThread。

引申:更多是对消息机制的理解

AsyncTask相比Handler有什么优点?不足呢?

技术点:AsyncTask、Handler

参考回答

  • Handler机制存在的问题:多任务同时执行时不易精确控制线程。
  • 引入AsyncTask的好处:创建异步任务更简单,直接继承它可方便实现后台异步任务的执行和进度的回调更新UI,而无需编写任务线程和Handler实例就能完成相同的任务。

使用AsyncTask需要注意什么?

技术点:AsyncTask

参考回答

  • 不要直接调用onPreExecute()、doInBackground()、onProgressUpdate()、onPostExecute()和onCancelled()方法
  • 一个异步对象只能调用一次execute()方法
  • 引申:谈谈AsyncTask初始化、五个核心方法如何配合进而体现Handler的作用

AsyncTask中使用的线程池大小?

技术点:AsyncTask

参考回答:在AsyncTask内部实现有两个线程池:

  • SerialExecutor:用于任务的排队,默认是串行的线程池,在3.0以前核心线程数为5、线程池大小为128,而3.0以后变为同一时间只能处理一个任务
  • THREAD_POOL_EXECUTOR:用于真正执行任务。

引申:谈谈对线程池的理解

 HandlerThread有什么特点?

技术点:HandlerThread

参考回答:HandlerThread是一个线程类,它继承自Thread。与普通Thread不同,HandlerThread具有消息循环的效果,这是因为它内部HandlerThread.run()方法中有Looper,能通过Looper.prepare()来创建消息队列,并通过Looper.loop()来开启消息循环。

 快速实现子线程使用Handler

技术点:HandlerThread

思路:不同于之前手动在子线程创建Looper再构建Handler的想法,这里从HandlerThread角度去快速实现在子线程使用Handler

参考回答:HandlerThread实现方法

  • 实例化一个HandlerThread对象,参数是该线程的名称;
  • 通过 HandlerThread.start()开启线程;
  • 实例化一个Handler并传入HandlerThread中的looper对象,使得与HandlerThread绑定;
  • 利用Handler即可执行异步任务;
  • 当不需要HandlerThread时,通过HandlerThread.quit()/quitSafely()方法来终止线程的执行。

 IntentService的特点?

技术点:IntentService

思路:和普通线程和普通Service比较突出其特点

参考回答: 不同于线程,IntentService是服务,优先级比线程高,更不容易被系统杀死,因此较适合执行一些高优先级的后台任务;不同于普通Service,IntentService可自动创建子线程来执行任务,且任务执行完毕后自动退出

 为何不用bindService方式创建IntentService?

技术点:IntentService

思路:从底层实现出发

参考回答:IntentService的工作原理是,在IntentService的onCreate()里会创建一个HandlerThread,并利用其内部的Looper实例化一个ServiceHandler对象;而这个ServiceHandler用于处理消息的handleMessage()方法会去调用IntentService的onHandleIntent(),这也是为什么可在该方法中处理后台任务的逻辑;当有Intent任务请求时会把Intent封装到Message,然后ServiceHandler会把消息发送出,而发送消息是在onStartCommand()完成的,只能通过startService()才可走该生命周期方法,因此不能通过bindService创建IntentService。

 线程池的好处、原理、类型?

技术点:线程池

参考回答:

  • (1)线程池的好处:
    • 重用线程池中的线程,避免线程的创建和销毁带来的性能消耗;
    • 有效控制线程池的最大并发数,避免大量的线程之间因互相抢占系统资源而导致阻塞现象;
    • 进行线程管理,提供定时/循环间隔执行等功能
  • (2)线程池的分类:
    • FixThreadPool:线程数量固定的线程池,所有线程都是核心线程,当线程空闲时不会被回收;能快速响应外界请求。
    • CachedThreadPool:线程数量不定的线程池(最大线程数为Integer.MAX_VALUE),只有非核心线程,空闲线程有超时机制,超时回收;适合于执行大量的耗时较少的任务
    • ScheduledThreadPool:核心线程数量固定,非核心线程数量不定;可进行定时任务和固定周期的任务。
    • SingleThreadExecutor:只有一个核心线程,可确保所有的任务都在同一个线程中按顺序执行;好处是无需处理线程同步问题。
  • (3)线程池的原理:实际上通过ThreadPoolExecutor并通过一系列参数来配置各种各样的线程池,具体的参数有:
    • corePoolSize核心线程数:一般会在线程中一直存活
    • maximumPoolSize最大线程数:当活动线程数达到这个数值后,后续的任务将会被阻塞

keepAliveTime非核心线程超时时间:超过这个时长,闲置的非核心线程就会被回收

  • unit:用于指定keepAliveTime参数的时间单位
  • workQueue任务队列:通过线程池的execute()方法提交的Runnable对象会存储在这个参数中。
  • threadFactory:线程工厂,可创建新线程
  • handler:在线程池无法执行新任务时进行调度

 ThreadPoolExecutor的工作策略?

技术点:线程池

参考回答:ThreadPoolExecutor的默认工作策略

  • 若程池中的线程数量未达到核心线程数,则会直接启动一个核心线程执行任务。
  • 若线程池中的线程数量已达到或者超过核心线程数量,则任务会被插入到任务列表等待执行。
    • 若任务无法插入到任务列表中,往往由于任务列表已满,此时如果
      • 线程数量未达到线程池最大线程数,则会启动一个非核心线程执行任务;
      • 线程数量已达到线程池规定的最大值,则拒绝执行此任务,ThreadPoolExecutor会调用RejectedExecutionHandler的rejectedExecution方法来通知调用者。

引申:ThreadPoolExecutor的拒绝策略

 什么是ANR?什么情况会出现ANR?如何避免?在不看代码的情况下如何快速定位出现ANR问题所在?

技术点:ANR
参考回答

  • ANR(Application Not Responding,应用无响应):当操作在一段时间内系统无法处理时,会在系统层面会弹出ANR对话框
  • 产生ANR可能是因为5s内无响应用户输入事件、10s内未结束BroadcastReceiver、20s内未结束Service
  • 想要避免ANR就不要在主线程做耗时操作,而是通过开子线程,方法比如继承Thread或实现Runnable接口、使用AsyncTask、IntentService、HandlerThread等
  • 引申:快读定位ANR方法:使用命令导出ANR日志,并分析关键信息,详见如何分析ANR

                                                              2019.5.30今日Android面试题 - 线程_第1张图片


                                                                                                                                  by .k

 

关注"编程v",每一天涨一点

STAY HUNGRY & STAY FOOLISH

2019.5.30今日Android面试题 - 线程_第2张图片

你可能感兴趣的:(android基础)