今天我们从面试的角度谈谈线程这个概念,我分享我个人的一些经验,希望能帮助到大家。
主线程
app启动的第一个线程,拥有很高的优先级,是主线程,是ui线程,对于app来说,16ms的帧同步信号需要在此线程调度,用户触摸屏事件需要在此线程响应,动画效果需要在此线程呈现。如果此线程效率不高,就会引发卡顿,掉帧,严重情况甚至会发生ANR。关于主线程会涉及到的面试问题,我个人比较喜欢了解以下几个方面:
- 主线程是如何判断?机制原理是什么?
- 主线程交互,AsyncTask、AsyncLayoutInflator、IntentService、Handler等的了解
- Dialog.show()、Toast.show()、PopWindow.showAtLocation()能不能在非主线程调用?
- UI组件是不是线程安全的?错误线程操作UI组件会引起什么问题?要如何处理?
- 什么情况下会引发ANR?如何防护避免ANR?
- 如何监控UI操作耗时?如何检查UI线程卡顿?
针对上面的问题,我们还可以追问一句,请举例说明/你平时有解决过/你是怎么应用的,这样可以进一步挖掘候选人编程习惯/风格,解决问题的思路/能力,临场分析/应对能力。如果候选人能一劳永逸,建立系统方案从代码检测到问题解决,那水平就很高。
工作线程
工作线程是主线程以外的一个概念,用户处理耗时问题。i/o操作,耗时操作,阻塞操作等就在此线程编写。这是一个与主线程对称的线程概念,我们就工作线程而言,已经没有太多的问题。于我个人而言,会了解一下候选人下面几个情况:
- 启动线程的方式有多少种,请列举一下。你平时是使用哪一种?为什么?
- 请简单介绍一下Service和IntentService的区别。
- 你是如何终止一个线程的执行的?
- 请你给出一个方案,如何监控统计一个线程的执行时间?
- 如何获得线程异常的线程堆栈信息?
如果想继续深入了解候选人的技能,还可以试着了解:
- 请简单介绍一下线程的几种状态?
- 请说详细明一下线程挂起/线程睡眠吗?
- sleep()、wait()、yield()有什么区别?
- notify()、notifyAll()有什么区别?
- 线程阻塞会有多少种实现方式?
可能还有其他的深入的知识点问题没有涉及到,请大家自行补充。
线程池
上面都是单独介绍一个单独的线程实例,关于线程池的知识就会突然增加,因为还包含了线程管理,通信,数据安全,同步,工作任务的协同。我们简单来列一下问题,答案在网上都有。
- 线程池的分类,针对线程池参数进行详细追问。你平时怎么使用?
- 线程安全的概念,以及如何保障线程安全?根据性能和效率继续追问。
- concurrent包的了解以及使用。举例说明。
- 线程协同。多个线程按顺序执行方案如何实现?
- 线程滥用引发oom问题以及处理方式?
- 如果涉及三方库使用,详细了解原理和源码逻辑。
- 死锁的概念?死锁的条件?死锁如何检测?如何避免?
- 锁的概念?锁的分类,公平/非公平,乐观/悲观等
线程池分类这里,很多人会不知道还有ForkJoinPool这个类型。另外可以针对性考察候选人对线程池的适用场景,譬如CachedThreadPool适用什么场景?在什么著名框架使用到?源码分析一下?
线程协同也有很复杂的应用场景,譬如音视频两种数据的处理协同,数据包如何分片,音频和视频如何同步?
如何统一app的线程池?如何阻断线程导致的内存泄漏?
协程
对于android来说这是一个新的概念,kotlin引入之后才有,如果说线程是进程概念的细分,那么协程就是线程概念的细分,大家可以去看看。关于kotlin协程,我会了解以下几个情况
- 启动协程有多少种方式?
- Flow和Channel的情况?为什么说flow是冷的,channel是热?
- 协程的实现机制?suspend关键字的含义?
- 参数为什么是any?
- 协程异常处理?
暂时想到就这么多,后续再补充。