美文网首页
Kotlin---协程的使用

Kotlin---协程的使用

作者: None_Ling | 来源:发表于2019-01-09 17:20 被阅读21次

第一个协程

在使用协程之前,需要保证Kotlin-Gradle-Plugin的版本高于1.3。目前最高的版本为1.3.11。否则编译会报错

首先来创建一个协程:

GlobalScope.launch { // 在后台启动一个新的协程并继续
        delay(1000L) // 非阻塞的等待 1 秒钟(默认时间单位是毫秒)
        println("World!...${Thread.currentThread().name}") // 在延迟后打印输出
}
println("Hello,...${Thread.currentThread().name}") // 协程已在等待时主线程还在继续

而打印出的结果为:

Hello,...main
World!...DefaultDispatcher-worker-1 @coroutine#1

可以看到通过GlobalScope.launch完成了:

  • 启动了新的线程,在该线程中创建了一个协程@coroutine#1
  • 在该协程中delay(1000L)等待了1秒后再输出日志。
  • 并且这样执行的协程,并不会阻塞主线程的执行

delay函数只能在协程中使用,否则编译不过,尽量避免使用GlobalScope.launch创建协程,当我们使用 GlobalScope.launch 时,我们会创建一个顶层协程。虽然它很轻量,但它运行时仍会消耗一些内存资源。如果我们忘记保持对新启动的协程的引用,它还会继续运行。

阻塞的协程runBlocking

GlobalScope.launch启动了一个线程创建新的协程,并没有阻塞当前线程。而如果想要在当前线程创建协程的话,则需要使用runBlocking

runBlocking {
      launch {
         Log.e(TAG,"${Thread.currentThread().name}...start delay 2000L")
         delay(2000L)
         Log.e(TAG,"${Thread.currentThread().name}...delay 2000L")
       }
      launch {
          Log.e(TAG,"${Thread.currentThread().name}...start delay 4000L")
          delay(4000L)
          Log.e(TAG,"${Thread.currentThread().name}...delay 4000L")
      }
      Log.e(TAG,"${Thread.currentThread().name}...launch 2 coroutines")
}

从输出结果,可以看到:

  • 直接在runBlocking中调用delay()会阻塞当前线程
  • runBlocking中调用launch()会开启新的协程,并且不会阻塞当前线程
  • runBlocking中调用launch()会在当前线程中执行协程
main @coroutine#1...launch 2 coroutines
main @coroutine#2...start delay 2000L
main @coroutine#3...start delay 4000L
main @coroutine#2...delay 2000L
main @coroutine#3...delay 4000L

等待协程执行完毕

无论通过GlobalScope.launch还是runBlocking中的launch,都会返回一个Job对象。通过Job.join函数,可以等待协程执行完毕再继续执行。

val job = GlobalScope.launch { // 启动一个新协程并保持对这个作业的引用
    delay(1000L)
    println("Hello,...${Thread.currentThread().name}")   
}
job.join() // 等待直到子协程执行结束
println("World!...${Thread.currentThread().name}")

输出结果:

Hello,...DefaultDispatcher-worker-1 @coroutine#2
World!...main @coroutine#1

CoroutineScope作用域

runBlocking中可以定义一个coroutineScope,而该函数的作用是为在这个函数中启动的协程添加作用域,只有当作用域内的协程都执行完毕后,才会继续执行当前线程。

runBlocking {
     Log.e(TAG, "${Thread.currentThread().name}...$this...start coroutineScope")
     coroutineScope {
          launch {
             delay(4000L)
             Log.e(TAG, "${Thread.currentThread().name}...$this...start delay 4000L")
          }
          launch {
             delay(3000L)
             Log.e(TAG, "${Thread.currentThread().name}...$this...start delay 3000L")
          }
     }
     Log.e(TAG, "${Thread.currentThread().name}...$this...after launch ")
}

输出的结果:

01-09 17:03:39.972  main...BlockingCoroutine{Active}@3fc800e3...start coroutineScope
01-09 17:03:39.972  main...StandaloneCoroutine{Active}@2affbae0...start delay 3000L
01-09 17:03:42.982  main...StandaloneCoroutine{Active}@23130199...start delay 4000L
01-09 17:03:43.982  main...BlockingCoroutine{Active}@3fc800e3...after launch 

可以看到,在最后的日志打印之前,会等待coroutineScope中的协程都执行完毕后,才会继续执行

挂起函数

当协程中的代码超级多的时候,通常都会把这些代码提取到一个函数中。但是这个函数必须使用suspend标识,否则编译错误,并且无法调用协程中到函数,比如delay()

  • 使用suspend标示的函数只能用于协程中,无法在其他函数中被调用
import kotlinx.coroutines.*

fun main() = runBlocking {
    launch { doWorld() }
    println("Hello,")
}

// 你的第一个挂起函数
suspend fun doWorld() {
    delay(1000L)
    println("World!")
}

相关文章

  • Kotlin---协程的使用

    第一个协程 在使用协程之前,需要保证Kotlin-Gradle-Plugin的版本高于1.3。目前最高的版本为1....

  • Kotlin---使用协程的异步

    协程间的通信 协程与协程间不能直接通过变量来访问数据,会导致数据原子性的问题,所以协程提供了一套Channel机制...

  • Kotlin---协程(Coroutine)介绍

    线程与进程 进程拥有代码和打开的文件资源、数据资源、独立的内存空间。 线程属于进程,是CPU执行的最小单元。一个进...

  • 协程.md

    协程协程中使用suspend修饰方法,代表该方法可在协程中挂起。但并不是协程方法必须使用suspend修饰协程和线...

  • XLua里使用协程

    在XLua里如何使用协程?有两种方式 使用Unity协程要想通过unity的StartCoroutine使用协程,...

  • 协程(三)IEnumerable、IEnumerator、for

    协程(一)基本使用协程(二)协程什么时候调用协程(三)IEnumerable、IEnumerator、foreac...

  • 协程(五)简单模拟协程

    协程(一)基本使用协程(二)协程什么时候调用协程(三)IEnumerable、IEnumerator、foreac...

  • 协程(一)基本使用

    协程(一)基本使用协程(二)协程什么时候调用协程(三)IEnumerable、IEnumerator、foreac...

  • 协程(六)有关优化

    协程(一)基本使用协程(二)协程什么时候调用协程(三)IEnumerable、IEnumerator、foreac...

  • 协程(二)协程什么时候调用

    协程(一)基本使用协程(二)协程什么时候调用协程(三)IEnumerable、IEnumerator、foreac...

网友评论

      本文标题:Kotlin---协程的使用

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