• 如何启动Kotlin协程


    启动协程的基本方式

    1.GlobalScope.launch

    代码示例:

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

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

    1.  context: CoroutineContext = EmptyCoroutineContext, 第一个参数是协程上下文,它的默认值是 EmptyCoroutineContext,如果不传这个参数,默认就会使用 EmptyCoroutineContext。也可以传入 Kotlin 官方为我们提供的 Dispatchers,来指定协程运行的线程池。(Dispatchers.IO、Dispatchers.Unconfined、Dispatchers.Main)
    2. start: CoroutineStart = CoroutineStart.DEFAULT,第二个参数是协程的启动模式,默认值是CoroutineStart.DEFAULT,CoroutineStart 是一个枚举类,一共有:DEFAULT、LAZY、ATOMIC、UNDISPATCHED。
    3. block: suspend CoroutineScope.() -> Unit,第三个参数是函数类型block,它的类型是suspend CoroutineScope.() -> Unit。本质是一个挂起函数。
    4. 函数的返回值是一个 Job,它其实代表的是协程的句柄,并不能返回协程的执行结果。

    2.runBlocking 启动协程

    代码示例

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

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

    1. fun testRunBlocking() {
    2. val runBlockingResult = runBlocking {
    3. delay(500L)
    4. return@runBlocking "HaHa"
    5. }
    6. println("result:$runBlockingResult")
    7. }
    8. result:HaHa

    runBlocking特点:

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

    3.async 启动协程

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

    代码示例

    1. fun testAsync() {
    2. runBlocking {
    3. val deferred = async {
    4. println("do async:${Thread.currentThread().name}")
    5. delay(1000L)
    6. return@async "do completed"
    7. }
    8. println("After async:${Thread.currentThread().name}")
    9. val result = deferred.await()
    10. println("Result is: $result")
    11. }
    12. }
    13. After async:main @coroutine#1
    14. do async:main @coroutine#2
    15. Result is: do completed
    1. public fun CoroutineScope.async(
    2. context: CoroutineContext = EmptyCoroutineContext,
    3. start: CoroutineStart = CoroutineStart.DEFAULT,
    4. block: suspend CoroutineScope.() -> T
    5. ): Deferred {
    6. val newContext = newCoroutineContext(context)
    7. val coroutine = if (start.isLazy)
    8. LazyDeferredCoroutine(newContext, block) else
    9. DeferredCoroutine(newContext, active = true)
    10. coroutine.start(start, coroutine, block)
    11. return coroutine
    12. }

    async注意点

    1.  async 启动协程以后,不会阻塞当前程序的执行流程。
    2.  async{}的返回值,是一个 Deferred 对象,它的 await() 方法,就可以拿到协程的执行结果。
    3. await只是等待执行完,并不是触发执行。

  • 相关阅读:
    spring-01-依赖注入
    使用香橙派 在Linux环境中安装并学习Python
    K8S存储
    【机器学习笔记】【数据预处理】
    truffle
    中小企业选择ERP系统时应关注的10个关键功能
    帷幄内容管理系统:从立人设、做内容到定向投流,品牌 KOS 体系打造「百万导购」
    【html5期末大作业】基于HTML+CSS+JavaScript管理系统页面模板
    BufferedReader读文件
    内核初始化
  • 原文地址:https://blog.csdn.net/zhangying1994/article/details/126689643