实现穿梭栈帧的魔法--协程

1,106 阅读1分钟

1. 协程-穿梭栈帧的魔法

协程的特性是代码中调用一次,实际会执行2次,第一次如果不满足条件先return一个状态,当满足条件的时候线程池会回调该方法执行第二次,而且还具有单例特性(指该函数第一次和第二次执行期间共享同一个上下文),妥妥的操作栈帧的魔法师。

2. 如何实现协程

前提:本文仅探讨kotlin协程实现

其实在反编译suspend函数反编译后就能知道协程的实现原理(以下)

github.com/yujinyan/ko…

//协程代码
//suspend fun foo() :Any{
//  delay(3000L)
//   val value =getCurrentTime()
//   Log.e("TAG", "result is $value")
//}
//等价代码
@suspend fun foo() {
    foo(object : Continuation<Any> {
        override fun resumeWith(result: Result<Any>) {
            val value = result.getOrThrow()
            Log.e("TAG", "result is $value")
        }
    })
}

@suspend fun foo(continuation: Continuation<Any>): Any {
    class FooContinuation : Continuation<Any> {
        var label: Int = 0

        override fun resumeWith(result: Result<Any>) {
            val outcome = invokeSuspend()
            if (outcome === COROUTINE_SUSPENDED) return
            continuation.resume(result.getOrThrow())
        }

        fun invokeSuspend(): Any {
            return foo(this)
        }
    }

    val cont = (continuation as? FooContinuation) ?: FooContinuation()
    return when (cont.label) {
        0 -> {
            cont.label++
            //异步延时任务
            AppExecutors.newInstance().otherIO.execute {
                Thread.sleep(3000L)
                val value = getCurrentTime()
                cont.resume(value)
            }
            COROUTINE_SUSPENDED
        }
        1 -> 1 // return 1
        else -> error("shouldn't happen")
    }
}

核心就是函数内匿名内部类的巧用,真的很妙

3. Demo地址有兴趣可以star一下

github.com/zjw-swun/Co…