美文网首页
Kotlin协程

Kotlin协程

作者: 竖起大拇指 | 来源:发表于2020-03-26 17:38 被阅读0次

什么是协程

协程:是一种更为灵活高效的用户线程,能够选择异步还是同步执行,指定运行的线程。
异步,同步编程:是指的协程能够选择自身的启动模式,在当前线程阻塞式运行,还是在后台异步执行;
指定运行线程:能够方便的选择执行的线程是后台线程还是UI主线程

进程,线程,协程关系

进程>线程>协程,即一个进程可以包含多个线程,一个线程上面可以运行多个协程。

启动方式

目前从非协程环境中启动协程环境主要有三种方式:

  • runBlocking :创建新的协程,运行在当前线程上,所以会阻塞当前线程,直到协程体以及所有子协程结束
  • GlobalScope.lanuch:启动一个新的线程,在新线程上创建运行协程,不阻塞当前线程
  • GlobalScope.asyn:启动一个新的线程,在新线程上运行协程,并且不阻塞当前线程,支持await获取返回值
  • withContext:可直接返回耗时任务的结果。一般来说,多个withContext任务是串行的。withContext可用来在协程中控制和切换部分任务执行所在的线程,接收的参数也是协程调度器,由此控制切换任务所在线程.
suspend关键字

kotlin中的一个关键字,它一般标识在一个函数的开头,用于表示该函数是个耗时操作,这个关键字主要作用就是为了作一个提醒,并不会因为添加了这个关键字该函数就会立即跑到子线程。suspend函数是只能再协程体内生效,在Kotlin协程中,当遇到supsend函数的时候,该协程会自动逃离当前所在的线程执行任务,此时原来协程所在的线程就继续干自己的事情,等到协程的suspend函数执行完成后又自动切回原来的线程继续往下走。

添加依赖

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.2'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.2'

runBlocking

创建新的协程运行在当前线程上,所以会阻塞当前线程,直到协程体结束
适用范围:
用于启动一个协程任务,通常只用于启动最外层的协程,例如:线程环境切换到协程环境

示列:

 fun main(args: Array<String>) = runBlocking { // this: CoroutineScope
            launch {
                delay(200L)
                println("Task from runBlocking:"+Thread.currentThread().name)
            }

            coroutineScope { // Creates a coroutine scope
                launch {
                    delay(500L)
                    println("Task from nested launch:"+Thread.currentThread().name)
                }

                delay(100L)
                println("Task from coroutine scope:"+Thread.currentThread().name) // This line will be printed before the nested launch
            }

            println("Coroutine scope is over:"+Thread.currentThread().name) // This line is not printed until the nested launch completes
        }

打印结果如下:

Task from coroutine scope:main
Task from runBlocking:main
Task from nested launch:main
Coroutine scope is over:main

GlobalScope.lanuch

创建新的协程,默认运行在后台新线程,并且不阻塞当前线程
适用范围:
需要启动异步线程处理的情况

示列

      fun main(args: Array<String>)= runBlocking { 
               var job=GlobalScope.launch {//启动一个新的协程
                println("GlobalLanuch:"+Thread.currentThread().name)
                delay(1000)
                println("World!")
            }
            println("Hello")
            println("runBlocking:"+Thread.currentThread().name)
            job.join()
        }

打印如下:

Hello
runBlocking:main
GlobalLanuch:DefaultDispatcher-worker-1
World!

GlobalScope.async

创建新的协程,默认运行在后台新的线程中,并且不阻塞当前线程,支持通过await获取返回值
适用范围:
特别是需要启动异步线程处理并等待处理结果返回的场景
示列:

       suspend fun getToken(): String { //suspend挂起的是协程本身不是本方法
            delay(300)
            println("getToken 开始执行,时间:  ${System.currentTimeMillis()}")
            return "ask"
        }

        suspend fun getResponse(token: String): String {
            delay(100)
            println("getResponse 开始执行,时间:  ${System.currentTimeMillis()}")
            return "response"
        }

        fun setText(response: String) {
            println("setText 执行,时间:  ${System.currentTimeMillis()}")
        }
        fun main(args: Array<String>) {
            println("协程 开始执行,时间:  ${System.currentTimeMillis()}")
             runBlocking {
                    var job=GlobalScope.launch {
                        //async 同 launch 唯一的区别就是 async 是有返回值的
                        var token=async {
                            return@async getToken()
                        }.await()

                        var response=async {
                            return@async getResponse(token)
                        }.await()

                        setText(response)
                    }
                    job.join()
                //job.start() - 启动协程,除了 lazy 模式,协程都不需要手      
               //动启动
                 //job.join() - 等待协程执行完毕
                //job.cancel() - 取消一个协程
                //job.cancelAndJoin() - 等待协程执行完毕然后再取消
           }
}

打印如下:

协程 开始执行,时间:  1585214992756
getToken 开始执行,时间:  1585214993133
getResponse 开始执行,时间:  1585214993243
setText 执行,时间:  1585214993243

withContext切换协程所在的线程

companion object{
          @JvmStatic
        fun main(args: Array<String>) {
           switchThread()
        }


        fun switchThread()= runBlocking {
            launch {
                println("start in thread ${Thread.currentThread().name}")
                val job= withContext(Dispatchers.IO){
                    delay(5000)
                    println("I am working in thread ${Thread.currentThread().name}")
                }

                println("end in thread :${Thread.currentThread().name}")
            }
        }
}

打印如下:

start in thread main
I am working in thread DefaultDispatcher-worker-1
end in thread :main

相关文章

网友评论

      本文标题:Kotlin协程

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