Kotlin协程的单线程 EventLoop 机制,其实就是 Android Handler 机制的原理,不过 Handler 是无限循环,当没有可执行的任务时会阻塞等待。 Android 为我们准备好了一个在 App 运行期间会一直运行的 main 线程,其在 ActivityThread 执行到 main 方法时会开启 loop,无限循环,精简的源码如下:
// android.app.ActivityThread.java
public static void main(String[] args) {
// 1. 以当前 main 线程 准备 mainLooper
Looper.prepareMainLooper();
// 2. 开始 loop 处理消息,当暂时没有消息时会阻塞 main 线程,直到有任务可以处理
Looper.loop();
// 3. 正常情况不会走到这里来
throw new RuntimeException("Main thread loop unexpectedly exited");
}
我们完全可以仿照 Handler 自己来实现一个简单的版本,实现类似于上面的无限循环和等待,看看下面的例子
class MyHandler {
private val threadLocal: ThreadLocal<BlockingQueue<Runnable>> = ThreadLocal()
private val blockingQueue: BlockingQueue<Runnable> = threadLocal.get() ?: LinkedBlockingQueue()
fun postRunnable(runnable: Runnable) = blockingQueue.put(runnable)
fun loop() {
while (true) blockingQueue.take().run() // 当queue中没有Runnable时,take会阻塞,直到queue中有值可取
}
}
val otherWork1 = Runnable { printlnWithThread("do work a") }
val otherWork2 = Runnable { printlnWithThread("do work X") }
fun main() {
val myHandler = MyHandler()
myHandler.postRunnable {
printlnWithThread("do work 1")
switchToBackThread(myHandler)
}
myHandler.postRunnable(otherWork1)
myHandler.postRunnable(otherWork2)
myHandler.loop()
println("Main thread loop unexpectedly exited")
}
fun switchToBackThread(myHandler: MyHandler) = thread {
printlnWithThread("do work 2")
myHandler.postRunnable { printlnWithThread("do work 3") }
}
运行结果如下:
main: do work 1 main: do work a main: do work X Thread-0: do work 2 main: do work 3 |
符合我们的预期