美文网首页
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