Kotlin协程的启动方式介绍

作者:且听真言 时间:2022-05-26 10:29:27 

启动协程的基本方式

1.GlobalScope.launch

代码示例:

fun testGlobalScope() {
   GlobalScope.launch {
       println("Coroutinue started!")
       delay(1000L)
       println("Hello World!")
   }
   println("After launch!")
   Thread.sleep(2000L)
   println("Process end!")
}
/**
* After launch!
* Coroutinue started!
* Hello World!
* Process end!
*/
@DelicateCoroutinesApi
public object GlobalScope : CoroutineScope {
   /**
    * Returns [EmptyCoroutineContext].
    */
   override val coroutineContext: CoroutineContext
       get() = EmptyCoroutineContext
}
public fun CoroutineScope.launch(
   context: CoroutineContext = EmptyCoroutineContext,
   start: CoroutineStart = CoroutineStart.DEFAULT,
   block: suspend CoroutineScope.() -> Unit
): Job {
   val newContext = newCoroutineContext(context)
   val coroutine = if (start.isLazy)
       LazyStandaloneCoroutine(newContext, block) else
       StandaloneCoroutine(newContext, active = true)
   coroutine.start(start, coroutine, block)
   return coroutine
}

launch函数是CoroutineScope的扩展函数,它有三个参数:

  • context: CoroutineContext = EmptyCoroutineContext, 第一个参数是协程上下文,它的默认值是 EmptyCoroutineContext,如果不传这个参数,默认就会使用 EmptyCoroutineContext。也可以传入 Kotlin 官方为我们提供的 Dispatchers,来指定协程运行的线程池。(Dispatchers.IO、Dispatchers.Unconfined、Dispatchers.Main)

  • start: CoroutineStart = CoroutineStart.DEFAULT,第二个参数是协程的启动模式,默认值是CoroutineStart.DEFAULT,CoroutineStart 是一个枚举类,一共有:DEFAULT、LAZY、 * IC、UNDISPATCHED。

  • block: suspend CoroutineScope.() -> Unit,第三个参数是函数类型block,它的类型是suspend CoroutineScope.() -> Unit。本质是一个挂起函数。

  • 函数的返回值是一个 Job,它其实代表的是协程的句柄,并不能返回协程的执行结果。

2.runBlocking 启动协程

代码示例

fun testRunBlocking2() {
   runBlocking {
       println("Coroutinue started!")
       delay(1000L)
       println("Hello World!")
   }
   println("After Launch")
   Thread.sleep(2000L)
   println("Process end")
}
/**
* Coroutinue started!
* Hello World!
* After Launch
* Process end
*/
@Throws(InterruptedException::class)
public actual fun <T> runBlocking(context: CoroutineContext, block: suspend CoroutineScope.() -> T): T {
   contract {
       callsInPlace(block, InvocationKind.EXACTLY_ONCE)
   }
   val currentThread = Thread.currentThread()
   val contextInterceptor = context[ContinuationInterceptor]
   val eventLoop: EventLoop?
   val newContext: CoroutineContext
   if (contextInterceptor == null) {
       // create or use private event loop if no dispatcher is specified
       eventLoop = ThreadLocalEventLoop.eventLoop
       newContext = GlobalScope.newCoroutineContext(context + eventLoop)
   } else {
       // See if context's interceptor is an event loop that we shall use (to support TestContext)
       // or take an existing thread-local event loop if present to avoid blocking it (but don't create one)
       eventLoop = (contextInterceptor as? EventLoop)?.takeIf { it.shouldBeProcessedFromContext() }
           ?: ThreadLocalEventLoop.currentOrNull()
       newContext = GlobalScope.newCoroutineContext(context)
   }
   val coroutine = BlockingCoroutine<T>(newContext, currentThread, eventLoop)
   coroutine.start(CoroutineStart.DEFAULT, coroutine, block)
   return coroutine.joinBlocking()
}

runBlocking是普通函数,第一个参数:context: CoroutineContext,协程上下文。第二个参数是函数类型,block: suspend CoroutineScope.() -> T,函数类型是有返回值类型 T 的,与 runBlocking 的返回值类型是一样的,runBlocking 其实是可以从协程当中返回执行结果的。

fun testRunBlocking() {
   val runBlockingResult = runBlocking {
       delay(500L)
       return@runBlocking "HaHa"
   }
   println("result:$runBlockingResult")
}
result:HaHa

runBlocking特点:

runBlocking 启动的协程会阻塞当前线程的执行。

3.async启动协程

使用 async{} 创建协程,可以通过它返回的Deferred拿到协程的执行结果。

代码示例

fun testAsync() {
   runBlocking {
       val deferred = async {
           println("do async:${Thread.currentThread().name}")
           delay(1000L)
           return@async "do completed"
       }
       println("After async:${Thread.currentThread().name}")
       val result = deferred.await()
       println("Result is: $result")
   }
}
After async:main @coroutine#1
do async:main @coroutine#2
Result is: do completed
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
}

async注意点

  • async 启动协程以后,不会阻塞当前程序的执行流程。

  • async{}的返回值,是一个 Deferred 对象,它的 await() 方法,就可以拿到协程的执行结果。

  • await只是等待执行完,并不是触发执行。

来源:https://blog.csdn.net/zhangying1994/article/details/126689643

标签:Kotlin,协程,启动方式
0
投稿

猜你喜欢

  • spring boot 注入 property的三种方式(推荐)

    2023-01-23 05:10:27
  • 一篇超详细的Spring Boot整合Mybatis文章

    2022-01-27 10:02:58
  • SpringBoot重写addResourceHandlers映射文件路径方式

    2022-05-26 19:02:40
  • C#实现读取注册表监控当前操作系统已安装软件变化的方法

    2022-01-04 08:07:04
  • java实现单链表倒转的方法

    2023-04-04 04:44:01
  • 详细讲解Java的泛型

    2021-07-06 02:31:24
  • Android仿百度谷歌搜索自动提示框AutoCompleteTextView简单应用示例

    2022-12-07 07:30:59
  • Java emoji持久化mysql过程详解

    2023-10-10 23:11:49
  • SpringBoot对Druid配置SQL监控功能失效问题及解决方法

    2023-06-10 21:31:24
  • SpringBoot 自定义+动态切换数据源教程

    2021-10-13 21:30:39
  • 常见的java面试题

    2023-11-26 18:03:44
  • 详解Java中的Vector

    2023-06-05 01:40:49
  • Oracle + Mybatis实现批量插入、更新和删除示例代码

    2022-01-18 16:05:58
  • java Spring MVC4环境搭建实例详解(步骤)

    2021-11-17 05:08:08
  • springboot docker jenkins 自动化部署并上传镜像的步骤详解

    2023-07-28 01:54:38
  • springmvc视图解析流程代码实例

    2023-02-14 04:33:39
  • Android应用 坐标系详细介绍

    2021-06-29 08:45:00
  • C# 基于TCP 实现扫描指定ip端口的方式示例

    2021-11-28 07:55:24
  • java中的静态代码块、构造代码块、构造方法详解

    2023-06-18 12:11:32
  • 使用Spring自定义实现IOC和依赖注入(注解方式)

    2023-09-16 04:42:35
  • asp之家 软件编程 m.aspxhome.com