@
- 反編譯后代碼分析
關于協程的一些理解
?協程掛起讓異步代碼可以像同步代碼一樣調用,但其本質還是同步,即協程體中的代碼其實是同步。
?
?因為協程也只是對線程池的封裝,所以需要了解些線程的一些知識。線程本身已經有的協程也會有,但是協程有的線程不一定有
?
?編譯器會為每一個掛起函數生成一個匿名內部類,其繼承SuspendLabmba類重寫其invokeSuspend方法,這個方法里面即為協程體的代碼【大致內容請先了解】
?
?編譯器會對協程體中的掛起函數和普通函數進行切割,切割時進行label的自增來保證之后代碼的執行順序,即協程保證運行順序的本質。【對比線程:進行PC程序計數器的控制來恢復執行】
?
?協程體中會添加一個label字段,標識接下來該運行協程體中的哪行代碼【即協程如何知道自己執行到哪步是用這個label完成的】(對比線程:線程存儲下一個代碼指令是用PC計數器來做的)
?
?協程體中的數據,看過之前那篇文章的人應該大致了解掛起函數其實就是匿名內部類,數據是保存在棧幀中的,(對比線程:也是通過棧幀中的局部變量表和操作數棧來存儲數據)
?
?協程體中碰到掛起函數會直接返回,等待掛起函數通知
?
?當我們調用掛起函數時都會傳入一個Continuation,掛起函數執行完正常退出或者拋異常退出這個時候外面的協程需要知道這個信息,怎么通知呢?通過Continuation的resumewith方法,這個方法會再次調用invokeSuspend取出label來保證之后執行代碼的順序,即協程自動恢復運行的本質
?
?(對比線程:方法正常執行完成之后有兩種情況1、正常結束,2.異常退出。其里面的PC計數器保證之后執行的代碼順序,也就是說協程在原本線程之上又加了一層控制)
?
?協程體中可以在開啟一個協程,也就是協程具有父子關系的本質。在協程伊始的時候會默認給一些默認數據(包括協程體運行在哪個線程即調度器其通過攔截器實現,執行狀態檢測用到的Job,攔截器等等)這些數據保存在協程的上下文中,
?
?當在協程體中又開啟了一個協程時,其會獲取父協程的上下文進行和自己的合并作為自己的上下文。
【簡而言之,和協程本身有關的數據保存在上下文中,和業務有關的代碼會放在匿名內部類中。】
?
基礎框架層源碼分析
val createCoroutine = suspend {
//掛起函數代碼
}.createCoroutine(object : Continuation<Unit> {
override val context: CoroutineContext
get() = TODO("Not yet implemented")
override fun resumeWith(result: Result<Unit>) {
//可從result中獲取返回值或異常
}
})
createCoroutine.resume(Unit)
?1.編譯器會對掛起函數做處理,讓他繼承SuspendCorunting,重寫其invokeSuspend方法,方法體為掛起函數中的代碼 2.當手動調用createCoroutine返回值的resume方法的時候,會調用到resumeWith函數,其里面會調用invokeSuspend也就是掛起函數體里面的代碼,之后兩種情況:3.碰到普通函數直接執行;碰到掛起函數傳入Continuation并直接返回一個標識代表其為掛起函數,這個時候協程直接退出,之后掛起函數執行完調用Continuation的resumeWith繼續執行方法體代碼【通過label確定順序】 4.在invokeSuepend中可以通過result獲取掛起函數執行的結果:異常或者返回值。進行對應處理。
?
實戰分析
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
GlobalScope.launch {
println("掛起點1開始")
delay(1000) //掛起點1
println("掛起點1結束")
hello() //掛起點2
println("掛起點2結束")
delay(1000) //掛起點3
println("掛起點3結束")
word() //掛起點4
}
}
//掛起函數,編譯器默認傳入Continuation
suspend fun hello(){
//再次掛起
withContext(Dispatchers.IO){
delay(1000)
println("hello")
}
}
suspend fun word(){
withContext(Dispatchers.IO){
delay(1000)
println("word")
}
}
-
封裝
+關注
關注
127文章
7990瀏覽量
143278 -
代碼
+關注
關注
30文章
4823瀏覽量
68904 -
線程
+關注
關注
0文章
505瀏覽量
19726
發布評論請先 登錄
相關推薦
評論