日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

Android Kotlin 协程async

發(fā)布時(shí)間:2024/9/30 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android Kotlin 协程async 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

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

往期精彩文章

Android Coroutines Channels

Kotlin實(shí)戰(zhàn)指南二十:flow

Kotlin實(shí)戰(zhàn)指南十六:Synchronized、Volatile

文章目錄

  • measureTimeMillis 統(tǒng)計(jì)一段代碼耗時(shí)
  • 使用默認(rèn)順序
  • 使用 async 并發(fā)
  • 惰性啟動(dòng)的 async
  • 構(gòu)建async 風(fēng)格的函數(shù)
  • 使用 async 的結(jié)構(gòu)化并發(fā)

measureTimeMillis 統(tǒng)計(jì)一段代碼耗時(shí)

內(nèi)斂函數(shù) measureTimeMillis{ } 可以很方便的統(tǒng)計(jì)一段代碼執(zhí)行的耗時(shí)。

使用:

GlobalScope.launch {val time = measureTimeMillis {delay(1000)Log.d("zyj-", "日志")}Log.d("zyj-", "耗時(shí):$time") }

輸出結(jié)果:

D/zyj-: 日志 D/zyj-: 耗時(shí):1010

使用默認(rèn)順序

定義兩個(gè)耗時(shí)函數(shù):

suspend fun doSomethingUsefulOne(): Int {delay(1000L) // 假設(shè)我們?cè)谶@里做了一些有用的事return 13 }suspend fun doSomethingUsefulTwo(): Int {delay(1000L) // 假設(shè)我們?cè)谶@里也做了一些有用的事return 29 }

使用默認(rèn)的順序調(diào)用:

val time = measureTimeMillis {val one = doSomethingUsefulOne()val two = doSomethingUsefulTwo()println("The answer is ${one + two}") } println("Completed in $time ms")

它的打印輸出如下:

The answer is 42 Completed in 2017 ms

從輸出結(jié)果上看,兩個(gè)耗時(shí)任務(wù)是串行的,總耗時(shí)= 耗時(shí)函數(shù)1 + 耗時(shí)函數(shù)2

使用 async 并發(fā)

如果 doSomethingUsefulOne 與 doSomethingUsefulTwo 之間沒有依賴,并且我們想更快的得到結(jié)果,讓它們進(jìn)行 并發(fā) 嗎?這就是async 可以幫助我們的地方。

在概念上,async 就類似于 launch。它啟動(dòng)了一個(gè)單獨(dú)的協(xié)程與其它所有的協(xié)程一起并發(fā)的工作。不同之處在于 launch 返回一個(gè) Job 并且不附帶任何結(jié)果值,而 async 返回一個(gè) Deferred—— 一個(gè)非阻塞 future, 這代表了一個(gè)將會(huì)在稍后提供結(jié)果的 promise。你可以使用 .await()在一個(gè)延期的值上得到它的最終結(jié)果, 但是 Deferred 也是一個(gè) Job,所以如果需要的話,你可以取消它。

val time = measureTimeMillis {val one = async { doSomethingUsefulOne() }val two = async { doSomethingUsefulTwo() }println("The answer is ${one.await() + two.await()}") } println("Completed in $time ms")

它的打印輸出如下:

The answer is 42 Completed in 1017 ms

這里快了兩倍,因?yàn)閮蓚€(gè)協(xié)程并發(fā)執(zhí)行。 請(qǐng)注意,使用協(xié)程進(jìn)行并發(fā)總是顯式的。

惰性啟動(dòng)的 async

可選的,async 可以通過將 start 參數(shù)設(shè)置為 CoroutineStart.LAZY 而變?yōu)槎栊缘摹?在這個(gè)模式下,只有結(jié)果通過 await 獲取的時(shí)候協(xié)程才會(huì)啟動(dòng),或者在 Job 的 start函數(shù)調(diào)用的時(shí)候。運(yùn)行下面的示例:

val time = measureTimeMillis {val one = async(start = CoroutineStart.LAZY) { doSomethingUsefulOne() }val two = async(start = CoroutineStart.LAZY) { doSomethingUsefulTwo() }// 執(zhí)行一些計(jì)算one.start() // 啟動(dòng)第一個(gè)two.start() // 啟動(dòng)第二個(gè)println("The answer is ${one.await() + two.await()}") } println("Completed in $time ms")

它的打印輸出如下:

The answer is 42 Completed in 1017 ms

因此,在先前的例子中這里定義的兩個(gè)協(xié)程沒有執(zhí)行,但是控制權(quán)在于程序員準(zhǔn)確的在開始執(zhí)行時(shí)調(diào)用 start。我們首先 調(diào)用 one,然后調(diào)用 two,接下來等待這個(gè)協(xié)程執(zhí)行完畢。

注意,如果我們只是在 println 中調(diào)用 await,而沒有在單獨(dú)的協(xié)程中調(diào)用 start,這將會(huì)導(dǎo)致順序行為,直到 await 啟動(dòng)該協(xié)程 執(zhí)行并等待至它結(jié)束,這并不是惰性的預(yù)期用例。 在計(jì)算一個(gè)值涉及掛起函數(shù)時(shí),這個(gè) async(start = CoroutineStart.LAZY)的用例用于替代標(biāo)準(zhǔn)庫(kù)中的 lazy 函數(shù)。

構(gòu)建async 風(fēng)格的函數(shù)

我們可以定義異步風(fēng)格的函數(shù)來 異步 的調(diào)用 doSomethingUsefulOne 和 doSomethingUsefulTwo 并使用 async 協(xié)程建造器并帶有一個(gè)顯式的 GlobalScope 引用。 我們給這樣的函數(shù)的名稱中加上“……Async”后綴來突出表明:事實(shí)上,它們只做異步計(jì)算并且需要使用延期的值來獲得結(jié)果。

// somethingUsefulOneAsync 函數(shù)的返回值類型是 Deferred<Int> fun somethingUsefulOneAsync() = GlobalScope.async {doSomethingUsefulOne() }// somethingUsefulTwoAsync 函數(shù)的返回值類型是 Deferred<Int> fun somethingUsefulTwoAsync() = GlobalScope.async {doSomethingUsefulTwo() }

使用

class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)// 我們可以在協(xié)程外面啟動(dòng)異步執(zhí)行val one = somethingUsefulOneAsync()val two = somethingUsefulTwoAsync()// 但是等待結(jié)果必須調(diào)用其它的掛起或者阻塞// 當(dāng)我們等待結(jié)果的時(shí)候,這里我們使用 `GlobalScope.launch{ }` 來阻塞主線程GlobalScope.launch {println("The- answer is ${one.await()} ${two.await()}")}} }

這種帶有異步函數(shù)的編程風(fēng)格僅供參考,因?yàn)檫@在其它編程語言中是一種受歡迎的風(fēng)格。在 Kotlin 的協(xié)程中使用這種風(fēng)格是強(qiáng)烈不推薦的, 原因如下所述。

考慮一下如果 val one = somethingUsefulOneAsync() 這一行和 one.await() 表達(dá)式這里在代碼中有邏輯錯(cuò)誤, 并且程序拋出了異常以及程序在操作的過程中中止,將會(huì)發(fā)生什么。 通常情況下,一個(gè)全局的異常處理者會(huì)捕獲這個(gè)異常,將異常打印成日記并報(bào)告給開發(fā)者,但是反之該程序?qū)?huì)繼續(xù)執(zhí)行其它操作。但是這里我們的 somethingUsefulOneAsync仍然在后臺(tái)執(zhí)行, 盡管如此,啟動(dòng)它的那次操作也會(huì)被終止。這個(gè)程序?qū)⒉粫?huì)進(jìn)行結(jié)構(gòu)化并發(fā),如下一小節(jié)所示。

使用 async 的結(jié)構(gòu)化并發(fā)

讓我們使用使用 async 的并發(fā)這一小節(jié)的例子并且提取出一個(gè)函數(shù)并發(fā)的調(diào)用 doSomethingUsefulOne 與 doSomethingUsefulTwo 并且返回它們兩個(gè)的結(jié)果之和。 由于 async 被定義為了 CoroutineScope上的擴(kuò)展,我們需要將它寫在作用域內(nèi),并且這是 coroutineScope 函數(shù)所提供的:

suspend fun concurrentSum(): Int = coroutineScope {val one = async { doSomethingUsefulOne() }val two = async { doSomethingUsefulTwo() }one.await() + two.await() }

這種情況下,如果在 concurrentSum 函數(shù)內(nèi)部發(fā)生了錯(cuò)誤,并且它拋出了一個(gè)異常, 所有在作用域中啟動(dòng)的協(xié)程都會(huì)被取消。

val time = measureTimeMillis {println("The answer is ${concurrentSum()}") } println("Completed in $time ms")

從上面的 main 函數(shù)的輸出可以看出,我們?nèi)匀豢梢酝瑫r(shí)執(zhí)行這兩個(gè)操作:

The answer is 42 Completed in 1017 ms

取消始終通過協(xié)程的層次結(jié)構(gòu)來進(jìn)行傳遞:

import kotlinx.coroutines.*fun main() = runBlocking<Unit> {try {failedConcurrentSum()} catch(e: ArithmeticException) {println("Computation failed with ArithmeticException")} }suspend fun failedConcurrentSum(): Int = coroutineScope {val one = async<Int> { try {delay(Long.MAX_VALUE) // 模擬一個(gè)長(zhǎng)時(shí)間的運(yùn)算42} finally {println("First child was cancelled")}}val two = async<Int> { println("Second child throws an exception")throw ArithmeticException()}one.await() + two.await() }

請(qǐng)注意,如果其中一個(gè)子協(xié)程(即 two)失敗,第一個(gè) async 以及等待中的父協(xié)程都會(huì)被取消:

Second child throws an exception First child was cancelled Computation failed with ArithmeticException 與50位技術(shù)專家面對(duì)面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖

總結(jié)

以上是生活随笔為你收集整理的Android Kotlin 协程async的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

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