美文网首页
Androdi kotlin Coroutines(协程)详解

Androdi kotlin Coroutines(协程)详解

作者: 水天滑稽天照八野滑稽石 | 来源:发表于2020-09-17 00:22 被阅读0次

Androdi kotlin Coroutines(协程)详解 (一)
Androdi kotlin Coroutines(协程)详解 (二)
Androdi kotlin Coroutines(协程)详解 (三)
Androdi kotlin Coroutines(协程)详解 (四)
Androdi kotlin Coroutines(协程)详解 (五)
Androdi kotlin Coroutines(协程)详解 (六)

五、几个重要的函数

5.1 async函数

创建协程并返回结果 [Deferred<T>] 的实现.异步实现,可以返回耗时任务的执行结果, 多个 async 任务是并行的, async返回的是一个 Deferred<T> ,需要调用其 await() 方法获取结果。

     public fun <T> CoroutineScope.async(
            context: CoroutineContext = EmptyCoroutineContext,
            start: CoroutineStart = CoroutineStart.DEFAULT,
            block: suspend CoroutineScope.() -> T
        ): Deferred<T> {
            val newContext = newCoroutineContext(context)
            val coroutine = if (start.isLazy)
                LazyDeferredCoroutine(newContext, block) else
                DeferredCoroutine<T>(newContext, active = true)
            coroutine.start(start, coroutine, block)
            return coroutine
        }

参考用法:

    private fun asyncCoroutine() {
        LogUtils.d("asyncCoroutine start  ${Thread.currentThread().name}")
        val result = GlobalScope.launch(Dispatchers.Main) {
            val one = async {
                delay(1000L) // 假设我们在这里做了一些有用的事
                return@async 13
            }
            val two = async {
                delay(1000L) // 假设我们在这里也做了一些有用的事
                return@async 29
            }
            LogUtils.d("The answer is ${one.await() + two.await()}")
        }
        LogUtils.d("asyncCoroutine end  ${Thread.currentThread().name}")
    }
5.1.1 结构化并发

提取出一个函数并发的调用 doSomethingUsefulOne 与 doSomethingUsefulTwo 并且返回它们两个的结果之和。 由于 async 被定义为了 CoroutineScope 上的扩展,我们需要将它写在作用域内,并且这是 coroutineScope 函数所提供的:

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

这种情况下,如果在 concurrentSum 函数内部发生了错误,并且它抛出了一个异常, 所有在作用域中启动的协程都会被取消。

    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) // 模拟一个长时间的运算
                42
            } finally {
                println("First child was cancelled")
            }
        }
        val two = async<Int> {
            println("Second child throws an exception")
            throw ArithmeticException()
        }
        one.await() + two.await()
    }

请注意,如果其中一个子协程(即 two )失败,第一个 async 以及等待中的父协程都会被取消

5.2 withContext函数

有返回结果,一般来说,多个 withContext 任务是串行的

    public suspend fun <T> withContext(
        context: CoroutineContext,
        block: suspend CoroutineScope.() -> T
    ): T {
        contract {
            callsInPlace(block, InvocationKind.EXACTLY_ONCE)
        }
        return ...
    }

示例如下:

     CoroutineScope(Dispatchers.Main).launch {
            val time1 = System.currentTimeMillis()
            val task1 = withContext(Dispatchers.IO) {
                delay(2000)
                Log.e("TAG", "1.执行task1.... [当前线程为:${Thread.currentThread().name}]")
                "one" //返回结果赋值给task1
            }
            val task2 = withContext(Dispatchers.IO) {
                delay(1000)
                Log.e("TAG", "2.执行task2.... [当前线程为:${Thread.currentThread().name}]")
                "two" //返回结果赋值给task2
            }
            Log.e("TAG", "task1 = $task1 , task2 = $task2 , 耗时 ${System.currentTimeMillis()-time1} ms [当前线程为:${Thread.currentThread().name}]")
            
        }
image.png

5.3 invoke函数

使用给定的[CoroutineDispatcher]调用指定的挂起块,挂起直到它完成,并返回结果。

5.4 launch

启动协程,挂起状态, lauch 是非阻塞的

5.5 delay函数

延时,可以看成Thread.sleep(),不过与sleep不同的是,delay函数是挂起状态,而sleep是阻塞的。

相关文章

网友评论

      本文标题:Androdi kotlin Coroutines(协程)详解

      本文链接:https://www.haomeiwen.com/subject/mbkxyktx.html