Kotlin协程--Coroutines的使用

622 阅读2分钟

1.1)依赖 api 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.0-M1'

所谓的协程官方介绍如下:

协程通过将复杂性放入库来简化异步编程。程序的逻辑可以在协程中顺序地表达,而底层库会为我们解决其异步性。该库可以将用户代码的相关部分包装为回调、订阅相关事件、在不同线程(甚至不同机器)上调度执行,而代码则保持如同顺序执行一样简单。

1.2) CoroutineScope,CoroutineContext,CoroutineDispatcher,Continuation 学习协程需要知道这几个类:

CoroutineScope-协程作作用域,包含CoroutineContext,可以理解为协程本身

CoroutineContext-It is an indexed set of Element instances.

CoroutineDispatcher-协程调度器,指定协程运行特定的thread or thread pool

Continuation–这个接口表示的是在一个挂起点之后,执行的代码片段,返回一个vaule

2.3)launch,async,withContext,Job , Deferred 启动一个简单的协程可以用launch{}或者async{}

这两者返回的都是Job,区别在于async返回的是Deferred,可以携带协程执行片段的返回值.

两者挂起时,都不会阻塞所在线程.

先看几个使用例子:

eg1:

fun coroutinesRunner() = runBlocking {
 test001()
}


private suspend fun test001() {
    coroutineScope {
 launch(CoroutineName("1")) {
 println("launch 01...")
            delay(3000)
            println("launch01 delay 3000ms")
        }.join()

        println("---after job finish system exit---")
    }


}
输出:

launch 01...
launch01 delay 3000ms
---after job finish system exit---

eg2:

模拟串行场景

private suspend fun test002() {

    coroutineScope {
 time {
 val registerDef = async {
 whichThread("registerDef")
                println("开始注册...")
                delay(3000)
                println("注册成功...")
                "openId:837983"
 }
 val loginDef = async {
 println("${registerDef.await()},开始登录...")
                delay(1000)
                println("登录成功...")
                "大明星,猪晓阳"
 }
 println("---------running----------")
            println("当前登录用户:${loginDef.await()}")
            println("---------end--------------")

        }
 }
}

输出:

---------running----------
tag:registerDef,threadName=main @coroutine#2
开始注册...
注册成功...
openId:837983,开始登录...
登录成功...
当前登录用户:大明星,猪晓阳
---------end--------------
耗时:4034
--------------next--------------------

registerDef.await()会使协程挂起,等待结果可用时,恢复协程继续执行剩余片段; 可以看到的是,当协程挂起时,线程没有被阻塞,println("---------running----------")还是直接执行了

eg3:

模拟并行场景

private suspend fun test003() {
    coroutineScope {
 time {
 val reqPic01 = async {
 println("获取猪晓阳果照片01...")
                delay(1500)
                println("获取猪晓阳果照片01成功...")
                "https://img01.xxx.jpg"
 }
 val reqPic02 = async {
 println("获取猪晓阳果照片02...")
                delay(1000)
                println("获取猪晓阳果照片02成功...")
                "https://img02.xxx.jpg"
 }

 println(
                "图片准备完成===>" +
                        "pic01=${reqPic01.await()}," +
                        "pic02=${reqPic02.await()}"
 )

        }

 }

}
输出:

获取猪晓阳果照片01...
获取猪晓阳果照片02...
获取猪晓阳果照片02成功...
获取猪晓阳果照片01成功...
图片准备完成===>pic01=https://img01.xxx.jpg,pic02=https://img02.xxx.jpg
耗时:1529
--------------next--------------------

eg4:

协程同步

private fun test004() {
    val mutex = Mutex()
    var counter = 0
 repeat(1000) {
 GlobalScope.launch {
 mutex.withLock {
 counter++
                println(counter)
            }

 }

 }
}
输出:

1
2
3
4
5
6
7
8
9
10
11
12

....

1000

使用Mutex().withLock{}可以保证协程同步,类似java重入锁