Kotlin Coroutine 初探(二)

Kotlin Coroutine 初探(二)

针对Coroutine的一些常用方法进行说明。

切换协程

使用withContext来进行协程的切换。

    fun testChangeContext() {
        launch {
            Log.e("ViewModel", "launch--start:${Thread.currentThread().name};${Thread.currentThread().id};${coroutineContext[Job]}")

            withContext(Dispatchers.IO) {
                delay(1000)
                Log.e("ViewModel", "withContext--IO:${Thread.currentThread().name};${Thread.currentThread().id};${coroutineContext[Job]}")
            }

            withContext(mChangeCoroutineContext) {
                delay(1000)
                Log.e("ViewModel", "withContext--self:${Thread.currentThread().name};${Thread.currentThread().id};${coroutineContext[Job]}")
            }

            mChangeCoroutineContext.close()
            Log.e("ViewModel", "launch--after:${Thread.currentThread().name};${Thread.currentThread().id};${coroutineContext[Job]}")
        }
    }

输出:
change_dispatcher

注意:协程的切换,还和构建时指定的模式相关。

异步执行

使用async+await,来进行异步任务。

    fun testAsync() {
        launch {
            Log.e("ViewModel", "launch--start:${Thread.currentThread().name};${Thread.currentThread().id};${coroutineContext[Job]}")

            withContext(Dispatchers.IO) {
                delay(1000)
                Log.e("ViewModel", "withContext--IO:${Thread.currentThread().name};${Thread.currentThread().id};${coroutineContext[Job]}")
            }

            val deferred = async {
                delay(3000)
                Log.e("ViewModel", "launch--async:${Thread.currentThread().name};${Thread.currentThread().id};${coroutineContext[Job]}")
                "async"
            }

            Log.e("ViewModel", "launch--after:${deferred.await()};${Thread.currentThread().name};${Thread.currentThread().id};${coroutineContext[Job]}")
        }
    }

输出:
coroutine_async

超时限制

使用withTimeout来限制任务的执行时间。

    var acquired = 0

    inner class Resource {
        init {
            acquired++
        } // Acquire the resource

        fun close() {
            acquired--
        } // Release the resource
    }

    fun testConcurrence() {
        runBlocking {
//            repeat(10) { // Launch 100K coroutines
                launch(Dispatchers.IO) {
                    Log.e("ViewModel", "launch:$acquired;${Thread.currentThread().id}")
                    val resource = withTimeout(200) { // Timeout of 200 ms
                        Log.e("ViewModel", "withTimeout:$acquired;${Thread.currentThread().id}")
                        delay(500) // Delay for 500 ms
                        val r = Resource() // Acquire a resource and return it from withTimeout block
                        Log.e("ViewModel","withTimeout--delay:$acquired;${Thread.currentThread().id}")
                        r
                    }
                    resource.close() // Release the resource
                    Log.e("ViewModel", "launch--close:$acquired;${Thread.currentThread().id}")
                }
//            }
            Log.e("ViewModel", "runBlocking:$acquired;${Thread.currentThread().id}")
        }
        // Outside of runBlocking all coroutines have completed
        Log.e("ViewModel", "acquired:$acquired") // Print the number of resources still acquired
    }

输出:
coroutine_timeout

协程流

目前包含flowchannelFlow

    fun testFlow() = launch {
        try {
            val flowCost = measureTimeMillis {
                flow<Int> {
                    Log.e("ViewModel", "flow")
                    for (i in 1..5) {
                        delay(1000)
                        emit(i)
                    }
                }.collect {
                    Thread.sleep(1000)
//                delay(1000)
                    Log.e("ViewModel", "flow:$it")
                }
            }
            Log.e("ViewModel", "flow--cost:$flowCost")

            delay(10000)
            Log.e("ViewModel", "flow--done")
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

输出:
coroutine_flow

    fun testChannel() {
        launch {
            try {
                val channelCost = measureTimeMillis {
                    channelFlow<Int> {
                        Log.e("ViewModel", "channelFlow")
                        for (i in 1..5) {
                            delay(1000)
                            send(i)
                        }

                    }.collect {
//                        delay(100)
                        Thread.sleep(1000)
                        Log.e("ViewModel", "channelFlow:$it")
                    }
                }
                Log.e("ViewModel", "channelFlow--cost:$channelCost")

                delay(10000)//防止parentScope已经完成
                Log.e("ViewModel", "channelFlow--done")
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }

输出:
coroutine_channel

区别:在默认的构建和接收模式下:flow 是 Cold Stream,在没有切换线程的情况下,生产者和消费者是同步非阻塞的;channel 是 Hot Stream,实现了生产者和消费者异步非阻塞模型。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值