Androdi kotlin Coroutines(协程)详解 (五)

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

五、几个重要的函数

5.1 async函数

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

     public fun  CoroutineScope.async(
            context: CoroutineContext = EmptyCoroutineContext,
            start: CoroutineStart = CoroutineStart.DEFAULT,
            block: suspend CoroutineScope.() -> T
        ): Deferred {
            val newContext = newCoroutineContext(context)
            val coroutine = if (start.isLazy)
                LazyDeferredCoroutine(newContext, block) else
                DeferredCoroutine(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 {
        try {
            failedConcurrentSum()
        } catch(e: ArithmeticException) {
            println("Computation failed with ArithmeticException")
        }
    }
    suspend fun failedConcurrentSum(): Int = coroutineScope {
        val one = async {
            try {
                delay(Long.MAX_VALUE) // 模拟一个长时间的运算
                42
            } finally {
                println("First child was cancelled")
            }
        }
        val two = async {
            println("Second child throws an exception")
            throw ArithmeticException()
        }
        one.await() + two.await()
    }

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

5.2 withContext函数

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

    public suspend fun  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(协程)详解 (五))