日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Kotlin实战指南十四:协程启动模式

發(fā)布時(shí)間:2024/9/30 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Kotlin实战指南十四:协程启动模式 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

轉(zhuǎn)載請(qǐng)標(biāo)明出處:https://blog.csdn.net/zhaoyanjun6/article/details/96008400
本文出自【趙彥軍的博客】


文章目錄

    • 協(xié)程啟動(dòng)
    • DEFAULT
    • LAZY
    • ATOMIC
    • UNDISPATCHED
    • 附錄
    • 參考資料

協(xié)程啟動(dòng)

說(shuō)了這么多線(xiàn)程,原因嘛,畢竟大家對(duì)它是最熟悉的。協(xié)程的 API 設(shè)計(jì)其實(shí)也與之一脈相承,我們來(lái)看一段最簡(jiǎn)單的啟動(dòng)協(xié)程的方式:

GlobalScope.launch {//do what you want }

那么這段代碼會(huì)怎么執(zhí)行呢?我們說(shuō)過(guò),啟動(dòng)協(xié)程需要三樣?xùn)|西,分別是 上下文、啟動(dòng)模式、協(xié)程體,協(xié)程體就好比 Thread.run 當(dāng)中的代碼,自不必說(shuō)。

本文將為大家詳細(xì)介紹 啟動(dòng)模式。在 Kotlin 協(xié)程當(dāng)中,啟動(dòng)模式是一個(gè)枚舉:

public enum class CoroutineStart {DEFAULT,LAZY,@ExperimentalCoroutinesApiATOMIC,@ExperimentalCoroutinesApiUNDISPATCHED; } 模式功能
DEFAULT立即執(zhí)行協(xié)程體
ATOMIC立即執(zhí)行協(xié)程體,但在開(kāi)始運(yùn)行之前無(wú)法取消
UNDISPATCHED立即在當(dāng)前線(xiàn)程執(zhí)行協(xié)程體,直到第一個(gè) suspend 調(diào)用
LAZY只有在需要的情況下運(yùn)行

DEFAULT

四個(gè)啟動(dòng)模式當(dāng)中我們最常用的其實(shí)是 DEFAULT 和 LAZY。

DEFAULT是餓漢式啟動(dòng),launch 調(diào)用后,會(huì)立即進(jìn)入待調(diào)度狀態(tài),一旦調(diào)度器 OK 就可以開(kāi)始執(zhí)行。我們來(lái)看個(gè)簡(jiǎn)單的例子:

class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)GlobalScope.launch(start = CoroutineStart.DEFAULT) {log(1)delay(1000)log(3)}log(2)} }

輸出結(jié)果是:

E/zhaoyanjun:: 2 main E/zhaoyanjun:: 1 DefaultDispatcher-worker-2 E/zhaoyanjun:: 3 DefaultDispatcher-worker-2

LAZY

LAZY 是懶漢式啟動(dòng),launch后并不會(huì)有任何調(diào)度行為,協(xié)程體也自然不會(huì)進(jìn)入執(zhí)行狀態(tài),直到我們需要它執(zhí)行的時(shí)候。這其實(shí)就有點(diǎn)兒費(fèi)解了,什么叫我們需要它執(zhí)行的時(shí)候呢?就是需要它的運(yùn)行結(jié)果的時(shí)候,launch調(diào)用后會(huì)返回一個(gè) Job實(shí)例,對(duì)于這種情況,我們可以:

  • 調(diào)用 Job.start,主動(dòng)觸發(fā)協(xié)程的調(diào)度執(zhí)行
  • 調(diào)用 Job.join,隱式的觸發(fā)協(xié)程的調(diào)度執(zhí)行

所以這個(gè)所謂的”需要“,其實(shí)是一個(gè)很有趣的措辭,后面你還會(huì)看到我們也可以通過(guò) await來(lái)表達(dá)對(duì) Deferred的需要。這個(gè)行為與 Thread.join不一樣,后者如果沒(méi)有啟動(dòng)的話(huà),調(diào)用 join 不會(huì)有任何作用

class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)val job = GlobalScope.launch(start = CoroutineStart.LAZY) {log(1)delay(1000)log(2)}log(3)job.start()log(4)} }

執(zhí)行結(jié)果:

E/zhaoyanjun:: 3 main E/zhaoyanjun:: 4 main E/zhaoyanjun:: 1 DefaultDispatcher-worker-1 E/zhaoyanjun:: 2 DefaultDispatcher-worker-1

ATOMIC

ATOMIC 只有涉及 cancel 的時(shí)候才有意義,cancel本身也是一個(gè)值得詳細(xì)討論的話(huà)題,在這里我們就簡(jiǎn)單認(rèn)為 cancel 后協(xié)程會(huì)被取消掉,也就是不再執(zhí)行了。那么調(diào)用cancel的時(shí)機(jī)不同,結(jié)果也是有差異的,例如協(xié)程調(diào)度之前、開(kāi)始調(diào)度但尚未執(zhí)行、已經(jīng)開(kāi)始執(zhí)行、執(zhí)行完畢等等。

為了搞清楚它與 DEFAULT 的區(qū)別,我們來(lái)看一段例子:

class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)val job = GlobalScope.launch(start = CoroutineStart.ATOMIC) {log(1)delay(1000)log(2)}log(3)job.cancel()log(4)} }

執(zhí)行結(jié)果:

E/zhaoyanjun:: 3 main E/zhaoyanjun:: 4 main E/zhaoyanjun:: 1 DefaultDispatcher-worker-1

我們創(chuàng)建了協(xié)程后立即cancel,但由于是 ATOMIC模式,因此協(xié)程一定會(huì)被調(diào)度,因此 1、3、4 一定都會(huì)輸出。
從輸出結(jié)果看不出什么,現(xiàn)在我們用 DEFAULT 模式來(lái)執(zhí)行一遍

class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)val job = GlobalScope.launch(start = CoroutineStart.DEFAULT) {log(1)delay(1000)log(2)}log(3)job.cancel()log(4)} }

執(zhí)行結(jié)果:

E/zhaoyanjun:: 3 main E/zhaoyanjun:: 4 main

對(duì)應(yīng)的,如果是DEFAULT 模式,在第一次調(diào)度該協(xié)程時(shí)如果 cancel就已經(jīng)調(diào)用,那么協(xié)程就會(huì)直接被 cancel 而不會(huì)有任何調(diào)用。

需要注意的是,cancel 調(diào)用一定會(huì)將該 job 的狀態(tài)置為 cancelling,只不過(guò)ATOMIC模式的協(xié)程在啟動(dòng)時(shí)無(wú)視了這一狀態(tài)。

我們使用線(xiàn)程的時(shí)候,想要讓線(xiàn)程里面的任務(wù)停止執(zhí)行也會(huì)面臨類(lèi)似的問(wèn)題,但遺憾的是線(xiàn)程中看上去與 cancel 相近的 stop 接口已經(jīng)被廢棄,因?yàn)榇嬖谝恍┌踩膯?wèn)題。不過(guò)隨著我們不斷地深入探討,你就會(huì)發(fā)現(xiàn)協(xié)程的 cancel某種意義上更像線(xiàn)程的 interrupt。

UNDISPATCHED

有了前面的基礎(chǔ),UNDISPATCHED 就很容易理解了。協(xié)程在這種模式下會(huì)直接開(kāi)始在當(dāng)前線(xiàn)程下執(zhí)行,直到第一個(gè)掛起點(diǎn),這聽(tīng)起來(lái)有點(diǎn)兒像前面的 ATOMIC,不同之處在于 UNDISPATCHED 不經(jīng)過(guò)任何調(diào)度器即開(kāi)始執(zhí)行協(xié)程體。當(dāng)然遇到掛起點(diǎn)之后的執(zhí)行就取決于掛起點(diǎn)本身的邏輯以及上下文當(dāng)中的調(diào)度器了。

附錄

log 代碼

fun log(mes: Int) {Log.e("zhaoyanjun:", "$mes ${Thread.currentThread().name}")}

參考資料

破解 Kotlin 協(xié)程(2) - 協(xié)程啟動(dòng)篇 https://www.bennyhuo.com/2019/04/08/coroutines-start-mode/


個(gè)人微信號(hào):zhaoyanjun125 , 歡迎關(guān)注

總結(jié)

以上是生活随笔為你收集整理的Kotlin实战指南十四:协程启动模式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。