Re-implement the works

前两天读到某某教授的一篇文章,作者提出一个“3遍阅读法(3-pass reading)”,最后一遍的要求叫"re-implement"。 这个词特别好。 我们读文章时, 或者因为使用某些知其然, 不知其所以然的类库, 知识时往往开始觉得很困惑, 经常用错。 源于我们对内在的原理不了解。 而“re-implement”要求我们从原作者的思维触发, 重铸作品, 达到知其所以然的目的。 当自己从头开始完全重铸意见作品时, 就能明白其中很多的条件和假设, 以及各种限制。 这些往往在我们使用是会忽略的因素。 大多数情况下, 一个工具,一套理论,一个开发类库, 都由其适用的条件和环境。 或许作者没有说清楚, 或者使用者没有仔细弄明白说明文档, 往往很容易用错。 这点对于程序员来说更甚。 往往拿到一个类库, 不会仔细阅读说明, 而是简单按照函数名称做一个猜测,忽略它的限制条件。 很多bug 就是由此引入的。 这些类库正常情况下使用良好, 然后在某些极端情况下会出问题。 带来各种bug。

由”re-implement” 一次我想到说其实类的设计充满这妥协和限制。 一个好的程序员应该站在类库作者的角度来考虑这些问题。简单说,即使不要求完全重写类库, 也应该在心里过一遍如果是自己来设计, 会如何做。 有条件的情况下, 多读读类库的源码。 一定会有很多收获。

Android 中的AsyncTask 就是这么一个很容易出错的类。 这个类android.os.AsyncTask 位于android.os 包下,虽然其实更应该是一个util类。这个类本是为了方便程序员写异步操作而设计, 然后它的API本省非常长。 而且在说明里告诉说这个类不适合长时间运行的任务,结果给出的例子就叫做DownloadingTask. 这是一个设计很糟糕的类。

对于它的设计, 如果没读过源码,可能会觉得有什么特别的, 因为位于android.os中。 然而它就是Handler和ThreadPool的简单封装而已。

代码中使用了SerialExecutorThreadPoolExecutor, 有一个sDefaultExecutor静态成员变量来控制, 可以通过setDefaultExecutor函数来控制。

所有的回调函数都是通过Handler 和sendMessage 来实现。 非常简单,是不是?

另外, ThreadPool 中初始化时定义最大128 个, 同时5个thread 执行。

Looper

Looper 是线程见消息同步的机制。 一个线程发生了某件事情, 如何实时通知另外一个线程? 这是一个通用问题。 常见做法是有一个线程一直死循环, 检查一个变量, 另外的线程发生什么事情就写这个变量。 一直死循环在检查变量的线程就是Looper 线程。 Android 中UI线程就有一个Looper, 当把本身的事情都做完之后, 就会开始死循环, 一旦有消息, 在死循环里完成那个消息触发的事件, 继续死循环。

Android 线程相关