前言:
前几天看了享学课堂Alvin老师讲的关于handler原理解析的文章,其中有一道MessageQueue的面试题引发了我的兴趣。原题是这样问题的:
MessageQueue中存储的Message数量有上限吗?为什么这么设计,能不能用阻塞队列做MessageQueue?(据传是百度面试题)
这个答案本身不难。MeesageQueue是一种队列的结构,设计上因为不能确定上限容量,所以代码中也没有对长度作出任何的限制。重点在于第二个问题,能否使用阻塞队列代替MessageQueue呢?
准备工作:
关于了解本问题的原因,必须要对Handler有一定的了解,如果没有,建议详细阅读下篇文章,提前做好知识储备。
android源码学习-Handler机制及其六个核心点_失落夏天的博客-CSDN博客_安卓开发handler机制
问题解析:
首先BlockQueue是一个接口,其实现类有LinkedBlockingDeque,DelayQueue,ArrayBlockingQueue等等。而MessageQueue甚至都没有去实现Queue的接口,而是参照队列的原理去实现的,其实两者都是属于一种带阻塞功能的队列。
所以,其实理论上BlockQueue确实可以替换MessageQueue的,并且不会发生ANR这类问题。那么google为什么还要自己实现,而不是直接使用现成的比如ArrayBlockQueue呢?
原因很简单,我觉得就是原有的BlockQueue功能不满足所有handler的所有需求。
原因1:
我们都知道Handler中有一种用法是sendMessageDelayed,那么如果MessageQueue里面有消息,但是还没有到执行时间怎么办呢?MessageQueue中有一个native用法nativePollOnce,可以传入等待时间,而BlockQueue就没这功能。
如果非要实现,那怎么办呢?就必须额外开一个线程,在弄一个未到执行时间队列2,在子线程中等到休眠时间到了之后,在把队列2中的Message对象挪到执行队列T1中,这样岂不是麻烦许多?
为什么不主线程休眠?主线程都休眠了,这期间如果新来消息还能响应吗?
原因2:
既然ArrayListQueue这一类都不能满足我们需求,但是BlockQueue是个接口类啊,我们自己生成一个类去实现BlockQueue接口类,在实现方法中按照我们实际需求去写,不就好了吗?比如也调用nativePollOnce这样的方法。
如果非要这样实现,按说也不是不行。这就要从设计模式去讲了,Message中有AidleHandler,异步消息,屏障消息等等,怎么去看,都不算一个纯粹的阻塞队列,而是包含了大量的业务逻辑与其中了。所以使用一个自定义类,而非标准的BlockQueue,无疑是更好的一个选择。
总结:
如果硬要使用阻塞队列BlockQueue去替代MessageQueue应该也是可以的,但是会带来各种各样的不方便。远远不如使用MessageQueue更合适。