首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

无挂起函数的Kotlin协程

基础概念

Kotlin 协程是一种轻量级的线程框架,用于简化异步编程。协程允许开发者编写看起来像同步代码的异步逻辑,从而避免回调地狱(callback hell)和提高代码的可读性。Kotlin 协程的核心概念包括:

  • CoroutineScope:定义协程的生命周期和作用域。
  • CoroutineContext:包含协程运行时的上下文信息,如 Job 和 Dispatcher。
  • Job:表示协程的工作单元,可以用来控制协程的生命周期。
  • Dispatcher:决定协程在哪个线程或线程池上执行。

无挂起函数的协程

在 Kotlin 中,挂起函数(suspend function)是协程的核心特性之一,它允许函数在执行过程中挂起(suspend)并在稍后恢复(resume)。然而,有时我们可能需要在不使用挂起函数的情况下使用协程。

相关优势

  1. 简化异步编程:协程提供了一种更直观的方式来处理异步操作,避免了回调地狱。
  2. 提高性能:协程比传统的线程更轻量级,可以在单个线程上运行多个协程,从而减少上下文切换的开销。
  3. 更好的资源管理:通过 CoroutineScope 和 Job,可以更方便地管理协程的生命周期和资源。

类型

Kotlin 协程主要分为以下几种类型:

  • GlobalScope:全局作用域,协程的生命周期与应用程序相同。
  • CoroutineScope:自定义作用域,可以指定协程的生命周期和上下文。
  • SupervisorJob:用于管理子协程,一个子协程的失败不会影响其他子协程。

应用场景

  1. 网络请求:处理异步的网络请求,如 API 调用。
  2. 数据库操作:执行异步的数据库读写操作。
  3. UI 更新:在 Android 开发中,用于更新 UI 组件。
  4. 定时任务:执行周期性的后台任务。

示例代码

以下是一个简单的示例,展示了如何在 Kotlin 中使用协程而不涉及挂起函数:

代码语言:txt
复制
import kotlinx.coroutines.*

fun main() = runBlocking {
    val job = launch {
        repeat(1000) { i ->
            println("I'm sleeping $i ...")
            delay(500L)
        }
    }
    delay(1300L) // delay a bit
    println("main: I'm tired of waiting!")
    job.cancelAndJoin() // cancels the job and waits for its completion
    println("main: Now I can quit.")
}

遇到问题及解决方法

问题:协程未按预期执行

原因

  • 可能是由于协程的作用域不正确,导致协程提前结束。
  • 可能是由于协程的上下文配置不正确,导致协程在错误的线程上执行。

解决方法

  • 确保使用正确的 CoroutineScope,并管理好协程的生命周期。
  • 检查协程的上下文配置,确保使用合适的 Dispatcher。

示例代码:解决协程未按预期执行的问题

代码语言:txt
复制
import kotlinx.coroutines.*

fun main() = runBlocking {
    val customScope = CoroutineScope(Dispatchers.Default)
    val job = customScope.launch {
        repeat(1000) { i ->
            println("I'm sleeping $i ...")
            delay(500L)
        }
    }
    delay(1300L) // delay a bit
    println("main: I'm tired of waiting!")
    job.cancelAndJoin() // cancels the job and waits for its completion
    println("main: Now I can quit.")
}

通过以上示例,可以看到如何正确配置协程的作用域和上下文,以确保协程按预期执行。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

【Kotlin 协程】协程的挂起和恢复 ① ( 协程的挂起和恢复概念 | 协程的 suspend 挂起函数 )

文章目录 一、协程的挂起和恢复概念 二、协程的 suspend 挂起函数 一、协程的挂起和恢复概念 ---- 函数 最基本的操作 是 : 调用 call : 通过 函数名或函数地址 调用函数 ; 返回...return : 函数执行完毕后 , 继续执行函数调用的下一行代码 ; 协程 在 调用 call 和 返回 return 基础上 , 又新增了两种 状态 : 挂起 Suspend : 暂停当前执行的协程..., 在子线程中执行异步任务后 , 会马上执行后续的代码 , 只是相当于 普通的多线程操作 ; 协程的作用就是 可以 顺序地执行 异步任务 和 主线程任务 , 其执行顺序按照代码顺序执行 ; 挂起 函数..., 只能在 协程体内部 或者 其它挂起函数 中调用 ; 协程外部不允许使用挂起函数 ; 在协程中 , 执行 挂起 Suspend 函数 , 将 挂起点的信息 记录下来 , 然后执行耗时操作 , 执行完毕后...){} 中 , 可以直接调用挂起函数 ; 挂起 函数 , 只能在 协程体内部 或者 其它挂起函数 中调用 ; 协程外部不允许使用挂起函数 ; 在协程中 , 执行 挂起 Suspend 函数 , 将 挂起点的信息

1.7K40

【Kotlin 协程】协程启动 ③ ( 协程组合并发 | 挂起函数串行执行 | 协程组合并发执行挂起函数 )

文章目录 一、挂起函数串行执行 二、协程组合并发执行挂起函数 一、挂起函数串行执行 ---- 在协程体中 , 连续使用多个挂起函数 , 这些函数的执行是顺序执行的 , 挂起函数 1 执行完毕后 , 才执行..., 可以将 主线程 包装成 协程 // measureTimeMillis 函数用于测量内部代码块执行的时间, 单位毫秒 ms val time =...577 ms 二、协程组合并发执行挂起函数 ---- 如果想要两个挂起函数并发执行 , 并且同时需要两个函数的返回值 , 则使用 async 协程构建器 , 启动两个协程 , 在协程体中执行两个并发函数..., 可以将 主线程 包装成 协程 // measureTimeMillis 函数用于测量内部代码块执行的时间, 单位毫秒 ms val time =..., 并发执行两个挂起函数 , 耗时 355 ms , 达到了并发执行减少执行时间的目的 ; 00:18:50.081 I 两个返回值相加 3 00:18:50.081 I 挂起函数执行耗时 355

70420
  • 【Kotlin 协程】协程的挂起和恢复 ② ( 协程挂起 和 线程阻塞 对比 )

    文章目录 一、协程挂起 和 线程阻塞 对比 1、协程挂起 2、线程阻塞 3、挂起和阻塞对 UI 的影响 4、挂起分析 一、协程挂起 和 线程阻塞 对比 ---- 挂起是协程中的概念 , 只能在协程中使用...; 阻塞是线程中的概念 , 可以在主线程和子线程中使用 ; 1、协程挂起 协程 挂起 操作 : 在协程中使用 delay 函数 , 挂起 20 秒时间 , 然后 20 秒后更新 UI ; delay...函数是 挂起 suspend 函数 ; // 创建协程 GlobalScope.launch(Dispatchers.Main) { delay(20000) // 主线程更新 UI...UI 的影响 协程 挂起 操作 不会出现 阻塞 UI 刷新的情况 , 挂起的 20 秒不影响 UI 刷新显示 ; 但是如果将主线程阻塞 , UI 不再刷新 , 会出现 ANR 崩溃异常 ; 图形化 GUI...协程中有挂起操作 , 会将挂起点的状态保存 , 同时协程停止执行 , 等待挂起函数执行完毕后 , 协程继续执行 ; 相当于阻塞的是协程 , 不会阻塞主线程 ;

    1.8K20

    破解 Kotlin 协程(6) - 协程挂起篇

    关键词:Kotlin 协程 协程挂起 任务挂起 suspend 非阻塞 协程的挂起最初是一个很神秘的东西,因为我们总是用线程的概念去思考,所以我们只能想到阻塞。不阻塞的挂起到底是怎么回事呢?...简单来说就是,对于 suspend 函数,不是一定要挂起的,可以在需要的时候挂起,也就是要等待的协程还没有执行完的时候,等待协程执行完再继续执行;而如果在开始 join 或者 await 或者其他 suspend...函数,如果目标协程已经完成,那么就没必要等了,直接拿着结果走人即可。...当然,字节码是比较抽象的,我这样写出来就是为了让大家更容易的理解协程是如何执行的,看到这里,相信大家对于协程的本质有了进一步的认识: 协程的挂起函数本质上就是一个回调,回调类型就是 Continuation...协程体的执行就是一个状态机,每一次遇到挂起函数,都是一次状态转移,就像我们前面例子中的 label 不断的自增来实现状态流转一样 如果能够把这两点认识清楚,那么相信你在学习协程其他概念的时候就都将不再是问题了

    1.2K30

    Kotlin协程解析系列(上):协程调度与挂起

    vivo 互联网客户端团队- Ruan Wen 本文是Kotlin协程解析系列文章的开篇,主要介绍Kotlin协程的创建、协程调度与协程挂起相关的内容 一、协程引入 Kotlin 中引入 Coroutine...coroutineScope 创建一个独立的协程作用域,直到所有启动的协程都完成后才结束自身。 它是一个挂起函数,需要运行在协程内或挂起函数内。...挂起函数只能在协程或另一个挂起函数中被调用,如果你在非协程中使用到了挂起函数,会报错。...协程其实就是一段可以挂起和恢复执行的运算逻辑,而协程的挂起通过挂起函数实现,挂起函数用状态机的方式用挂起点将协程的运算逻辑拆分成不同的片段,每次运行协程执行不同的逻辑片段。...协程挂起: 挂起函数是一个可启动、暂停和恢复的函数,被suspend修饰的函数在协程运行时不是一定会被挂起的。 挂起函数的挂起实现原理就是状态机的状态转移。

    2K40

    Kotlin协程实现原理:挂起与恢复

    今天我们来聊聊Kotlin的协程Coroutine。 如果你还没有接触过协程,推荐你先阅读这篇入门级文章What? 你还不知道Kotlin Coroutine?...Kotlin协程实现原理:Suspend&CoroutineContext Kotlin协程实现原理:CoroutineScope&Job Kotlin协程实现原理:ContinuationInterceptor...协程的所谓非阻塞式挂起与恢复又是什么? 协程的内部实现原理是怎么样的? ... 接下来的一些文章试着来分析一下这些疑问,也欢迎大家一起加入来讨论。 挂起 协程是使用非阻塞式挂起的方式来保证协程运行的。...而它另一个关键作用是起到挂起协程的标识。 协程运行的时候每遇到被suspend修饰的方法时,都有可能会挂起当前的协程。 注意是有可能。...由挂起自身的协程,从而触发挂起父类的协程。

    2.3K10

    【Kotlin 协程】协程中的多路复用技术 ② ( select 函数原型 | SelectClauseN 事件 | 查看挂起函数是否支持 select )

    一、select 函数原型 ---- 在上一篇博客 【Kotlin 协程】协程中的多路复用技术 ① ( 多路复用技术 | await 协程多路复用 | Channel 通道多路复用 ) 中 , 介绍了...协程多路复用技术 , 多路复用 主要使用 select 代码块 实现 , 在 select 代码块中 调用多个协程的 onAwait 函数 , 哪个协程先返回数据 , 就选择该协程的数据作为返回值 ;..._clauses_指定的多个挂起函数的结果 * 在此选择调用的[builder]范围内。...相反,每个可选择的挂起函数都具有 * 对应的非挂起版本,可以与常规的“when”表达式一起使用来选择一个 * 的选项,如果没有选项可以立即选择,则执行默认(' else ')操作。...如果当前协程的[Job]被取消或完成 * 函数挂起后,该函数立即恢复[CancellationException]。 * 有**立即取消保证**。

    1.2K20

    【Kotlin 协程】协程启动 ⑤ ( 协程作用域构建器 | runBlocking 函数 | coroutineScope 函数 | supervisorScope 函数 )

    函数 ) 1、协程作用域构建器概念 2、coroutineScope 协程作用域构建器 示例 3、supervisorScope 协程作用域构建器 示例 一、结构化并发 ---- 在 【Kotlin...实现 CoroutineScope 协程作用域接口 ) 【Kotlin 协程】协程底层实现 ④ ( 结构化并发 | viewModelScope 作用域示例 ) 博客中介绍了 结构化并发 ; 结构化并发的作用...: CoroutineContext, block: suspend CoroutineScope.() -> T): T coroutineScope 是 挂起函数 , 只能在 协程体 中使用 ,...runBlocking 可以在普通的函数中执行 , 将主线程包装成了协程体 ; 但是 coroutineScope 函数 由于是 挂起函数 , 只能在 协程体 中使用 ; 该 coroutineScope....() -> R): R supervisorScope 函数 构建的 协程作用域 , 如果有一个 子协程 执行失败 , 其它子协程继续执行 , 不会受到执行失败的子协程影响 ; 函数原型如下 : public

    53930

    【Kotlin 协程】协程异常处理 ② ( SupervisorJob 协程 | supervisorScope 协程作用域构建器函数 )

    文章目录 一、SupervisorJob 协程 二、supervisorScope 协程作用域构建器函数 在上一篇博客介绍了 协程异常处理 【Kotlin 协程】协程异常处理 ① ( 根协程异常处理..., 会将异常 传递给 父协程 , 父协程会执行如下操作 : ① 取消子协程 : 不仅仅取消产生异常的子协程 , 该父协程下所有的子协程都会取消 ; ② 取消父协程 : 将父协程本身取消 ; ③ 向父协程的父协程传播异常...: 继续将异常传播给 父协程的父协程 ; 这样就会导致 某个子协程一旦出现异常 , 则 兄弟协程 , 父协程 , 父协程的兄弟协程 , 父协程的父协程 等等 都会被取消 , 这样牵连太大 , 因此本篇博客中引入几种异常处理机制解决上述问题...协程作用域 调用 launch 构建器函数 , 即可 创建 SupervisorJob 协程 , 这些协程可以自己处理异常 , 不会向父协程传递异常 ; 代码示例 : // 先创建 Supervisor...协程作用域构建器函数 ---- 使用 supervisorScope 作用域构建器函数 , 可以直接创建一个 SupervisorScope 协程作用域 , 在该作用域中定义的 协程 , 都是 SupervisorJob

    77210

    Kotlin协程-特殊的阻塞协程

    阻塞协程是种特殊的协程启动方式,一般是用 runBlocking{} 扩起来一段协程。...首先是父协程得到执行,然后才是子协程。 重点是这两段协程都在同一个线程main里完成。这里就带来一个有趣的问题, runBLocking{}和平时常用的launch有什么区别?...这里给出结果,改用GlobalScope.launch之后,子协程会在一个独立的线程里运行。 runBlocking 在kotlin协程官网上对于这个api的解释是桥接阻塞与非阻塞的世界。...在创建完coroutine后就进入派发流程了,这部分和Kotlin协程-一个协程的生命周期中的逻辑比较相似,下面也会讲到。...这个问说明,runBLocking{}这种协程,它的运行逻辑是先把父协程放队列里,然后取出来执行,执行完毕再把子协程入队,再出队子协程,用同样的方式递归。

    2.5K20

    协程-无栈协程(下)

    thread_inst_pt用于缓存协程的状态信息,而外层用name->RoleData的映射关系管理协程及其他协程中间态数据;     需要注意的是——以protothread来说: ·对于无栈协程来说...,因为不存在指针等信息,所以无栈协程的所有信息是可以缓存在共享内存的,因此进程可以通过共享内存在重启的环境下,也不会导致协程中断; ·但是这种恢复也是有条件的,在protothread中是用行号进行协程恢复...,引发执行流程错乱(所以在使用这类库的时候,应该将函数的实现和协程主流程分开,以避免因为逻辑修改导致协程不可恢复的场景);     对于无栈协程来说,执行流的恢复只是通过找到下一条指令的执行地址,但是不包括上下文...,这意味着无栈协程里面不能有局部变量,需要我们手动把后面需要用到的局部变量缓存起来。     ...此外这里无栈协程是通过switch-case实现的,嵌套的switch-case会产生问题,限制比较多,所以也不适用于线上场景。

    87020

    Android面试题之Kotlin 协程的挂起、执行和恢复过程

    协程挂起和恢复时保存的状态和上下文 1.1 状态信息 协程的状态信息主要包括: 局部变量:函数当前执行到的位置以及所有局部变量的值。...挂起点:协程挂起的位置,这个位置通常是代码中的一个挂起点(suspend函数)。 调用栈:它对应当前执行的协程堆栈帧,可以看作是对函数调用链的保存。...2.2 Continuation Kotlin中的挂起函数实质上会被编译器转换成带有回调的 Continuation 对象。...协程挂起后切换到其他线程执行 当协程遇到挂起点(如 delay, await 等 suspend 函数)时,它会触发挂起机制,具体步骤如下: 3.1 挂起点的处理 当协程在挂起点被挂起时,当前函数状态和局部变量会被保存到...总结 综上所述,Kotlin 协程在挂起和恢复过程中,通过调度器实现线程的切换和任务调度: 挂起点保存当前状态由Continuation管理。 调度器控制挂起后的线程控制权交还。

    20410

    Kotlin协程开篇

    《Kotlin协程》均基于Kotlinx-coroutines 1.3.70 新开个坑,专门讲kotlin的协程。聊协程之前先说一下具体聊的是协程的什么内容。 · 协程是什么? · 什么时候用协程?...· 协程的核心是什么? · kotlin的协程和其他语言的协程有什么异同? kotlin的协程的出现其实比kotlin语言还晚一点。在当前这个版本,协程甚至都还处于一个不稳定的迭代版本中。...存活 } 上面的代码是一个常规启动协程的方式,关键函数只有 launch,delay,这两个函数是kotlin协程独有的。...这个问题涉及到Kotlin协程的Scope,调度,也是协程的实现核心逻辑 Kotlin不是第一个提出协程的 实际上在Kotlin之前就有不少语言实践了协程这个概念。比如python,golang。...python的协程是基于yield关键字进行二次封装的,虽然在高层抽象上也是以函数作为协程粒度,但对比golang差的太远。

    90420

    Kotlin 协程总结

    c.suspend suspend是 Kotlin 协程最核心的关键字,几乎所有介绍 Kotlin 协程的文章和演讲都会提到它。它的中文意思是「暂停」或者「可挂起」。...所以这个 suspend,其实并不是起到把任何把协程挂起,或者说切换线程的作用。 真正挂起协程这件事,是 Kotlin 的协程框架帮我们做的。...所以我们想要自己写一个挂起函数,仅仅只加上 suspend 关键字是不行的,还需要函数内部直接或间接地调用到 Kotlin 协程框架自带的 suspend 函数才行。 3.suspend 的意义?...四、总结 协程就是切线程; 挂起就是可以自动切回来的切线程; 挂起的非阻塞式指的是它能用看起来阻塞的代码写出非阻塞的操作,就这么简单。 参考: 1,Kotlin 的协程用力瞥一眼 - 学不会协程?...很可能因为你看过的教程都是错的 2,Kotlin 协程的挂起好神奇好难懂?今天我把它的皮给扒了 3,到底什么是「非阻塞式」挂起?协程真的更轻量级吗?

    3.3K11

    破解 Kotlin 协程(5) - 协程取消篇

    关键词:Kotlin 协程 协程取消 任务停止 协程的任务的取消需要靠协程内部调用的协作支持,这就类似于我们线程中断以及对中断状态的响应一样。 1. 线程的中断 我们先从大家熟悉的话题讲起。...suspendCoroutine,这就是为了让我们的挂起函数支持协程的取消。...再谈 Retrofit 的协程扩展 4.1 Jake Wharton 的 Adapter 存在的问题 我在破解 Kotlin 协程 - 入门篇(https://www.bennyhuo.com/2019...直接解决还是比较困难的,因为 CompletableDeferred 构造所处的调用环境不是 suspend 函数,因而也没有办法拿到(很可能根本就没有!)父协程。...接着我们将之前我们一直提到的回调转协程的例子进一步升级,支持取消,这样大家就可以轻易的将回调转变为协程的挂起调用了。

    1.8K50

    破解 Kotlin 协程(2) - 协程启动篇

    log(3) job.join() log(4) } 说明: main 函数 支持 suspend 是从 Kotlin 1.3 开始的。...另外,main 函数省略参数也是 Kotlin 1.3 的特性。后面的示例没有特别说明都是直接运行在 suspend main 函数当中。...对于 ATOMIC 模式,我们已经讨论过它一定会被启动,实际上在遇到第一个挂起点之前,它的执行是不会停止的,而 delay 是一个 suspend 函数,这时我们的协程迎来了自己的第一个挂起点,恰好 delay...我们在前面提到我们的示例都运行在 suspend main 函数当中,所以 suspend main 函数会帮我们直接启动一个协程,而我们示例的协程都是它的子协程,所以这里 5 的调度取决于这个最外层的协程的调度规则了...相信大家读完对于协程的执行机制有了一个大概的认识,同时对于协程的调度这个话题想必也非常好奇或者感到困惑,这是正常的——因为我们还没有讲嘛,放心,调度器的内容已经安排了 : ) 附录 log 函数的定义:

    1K30

    破解 Kotlin 协程(3) - 协程调度篇

    关键词:Kotlin 异步编程 协程 上一篇我们知道了协程启动的几种模式,也通过示例认识了 launch 启动协程的使用方法,本文将延续这些内容从调度的角度来进一步为大家揭示协程的奥义。 ? 1....我们通过 launch启动了一个协程,为它指定了我们自己的拦截器作为上下文,紧接着在其中用 async 启动了一个协程, async 与 launch 从功能上是同等类型的函数,它们都被称作协程的 Builder...其次, delay 是挂起点,1000ms 之后需要继续调度执行该协程,因此就有了 ③ 处的日志。 最后,④ 处的日志就很容易理解了,正是我们的返回结果。...Kotlin 协程设计者也特别害怕大家注意不到这一点,还特地废弃了两个 API 并且开了一个 issue 说我们要重做这套 API,这两个可怜的家伙是谁呢?...$result") }.join() log(6) } 这里面除了 delay 那里有一次不可避免的线程切换外,其他几处协程挂起点的继续操作

    76920

    java协程框架quasar和kotlin中的协程

    而反观协程,基于固定的几个线程调度,可以轻松实现百万级的协程处理,而且内存稳稳的。 后记 最后,博主以为Quasar只是一个框架层面的东西,所以就又去看了下同样是jvm语言的kotlin的协程。...,有种震惊的赶脚,kotlin的同步模型牛逼呀,瞬时感觉到发现了java里的骚操作了,可以使用kotlin的协程来代替java中的多线程操作。...所以就有下面这个kotlin协程实现的代码: @Service class KotlinAsyncService(private val weatherService: GetWeatherService...io操作,io操作是阻塞的,协程的并发也就变成了调度协程的几个线程的并发了。...协程里的delay挂起函数,会立马释放线程到线程池,但是当真正的io阻塞的时候也就和真正的线程sleep一样了,并没有释放当前的线程。所以这些对比都没有太大的意义。

    54430
    领券