Ktor練功場#5筆記-非同步處理

YungHsin
6 min readSep 21, 2020

--

本次練功場重點:

非同步處理

這次講者用了跑跑薑餅人的角色來解釋非同步處理,只有來線上的聽課才能看見投影片,所以大家還是實際來上課才能聽到精彩的解說,筆者這次很偷懶直接就進入實作寫Code了!

實作練習

(1)依序執行

這次練習連續呼叫三個自製API(可以參考上一回的API練習製作),分別都會delay 2秒後印出結果,印出內容分別是hello1, hello2, hello3。

get("/json/jackson1") {
delay(2000)
call.respond(mapOf("hello" to "hello1"))
}
get("/json/jackson2") {
delay(2000)
call.respond(mapOf("hello" to "hello2"))
}
get("/json/jackson3") {
delay(2000)
call.respond(mapOf("hello" to "hello3"))
}
}

然後在/根路徑裡加入開始結束時間,記下花費時間,然後把結果都印在網頁上

get("/") {
val beginTime = System.currentTimeMillis()

val msg1 = client.get<JsonSampleClass>("http://0.0.0.0:8080/json/jackson1")
val msg2 = client.get<JsonSampleClass>("http://0.0.0.0:8080/json/jackson2")
val msg3 = client.get<JsonSampleClass>("http://0.0.0.0:8080/json/jackson3")

val resultMsg = "${msg1}${msg2}${msg3}"

val endTime = System.currentTimeMillis()

call.respondText("${resultMsg}\n costTime(millionseconds):${endTime-beginTime}")
}

如果直接執行的話,不意外就是要一個等一個API回傳回來,然後在網頁畫面上會印出hello1, hello2, hello3,並且至少會花個3x2秒約6秒的執行時間。

(2)加上async

我們試著在每隻API加上async,執行後來看

get("/") {
val beginTime = System.currentTimeMillis()
val msg1 = async{ client.get<JsonSampleClass>("http://0.0.0.0:8080/json/jackson1") }
val msg2 = async{ client.get<JsonSampleClass>("http://0.0.0.0:8080/json/jackson2") }
val msg3 = async{ client.get<JsonSampleClass>("http://0.0.0.0:8080/json/jackson3") }
val resultMsg = "${msg1}${msg2}${msg3}" val endTime = System.currentTimeMillis() call.respondText("${resultMsg}\n costTime(millionseconds):${endTime-beginTime}")
}

果然呼叫API執行的時間變短了,幾乎不用到一秒,但是印出來怎麼是DeferedCorutine這個結果呢? 那是因為併發出去後每個API開始執行,到了等待期就會暫停下來,讓其他的任務繼續執行,而我們沒有特別去接下每個任務結束後的結果,照程式的邏輯就是呼叫完就直接跑到call.respondText印出結果了。

(3)加上await()

加上async好像真的讓執行時間變短,但是那要怎麼等待async的API真正執行完後的結果呢? 只要在印出結果的地方加上await()就可以了。

get("/") {
val beginTime = System.currentTimeMillis()
val msg1 = async{ client.get<JsonSampleClass>("http://0.0.0.0:8080/json/jackson1") }
val msg2 = async{ client.get<JsonSampleClass>("http://0.0.0.0:8080/json/jackson2") }
val msg3 = async{ client.get<JsonSampleClass>("http://0.0.0.0:8080/json/jackson3") }
val resultMsg = "${msg1.await()}${msg2.await()}${msg3.await()}" val endTime = System.currentTimeMillis() call.respondText("${resultMsg}\n costTime(millionseconds):${endTime-beginTime}")
}

再實際執行一次,看到的結果就會跟依序執行一樣是印出hello1, hello2, hello3,不過這邊但是等待API回應回來還是需要delay 2秒的等待時間,所以回頭看執行時間差不多就是花費2秒左右了,這樣才是我們想要的結果。

以上就是Ktor練功場第五堂的內容,歡迎各位也一起來練功場學習Ktor囉! 隔週一起來練功!

--

--

YungHsin
YungHsin

No responses yet