【Coroutines】Full Understanding of Kotlinx.Corutines Framework

文章目录

          • What is Corutines
          • Difference between Corutine and Thread
          • Fast Usage
          • Suspend Function
          • Advanced Usage of Coroutine
          • Coroutine Essentials
          • CoroutineContext
          • CoroutineScope
          • Predefined CoroutineScope
          • Predefined Dispatchers
          • Predefined CoroutineStart
          • Job
          • Create a Coroutine
          • ContinuationInterceptor
          • CoroutineExceptionHandler

What is Corutines

corutines is a modern way of async programming

a corutine is a async code block that supports suspend and resume

typically the code block looks like a synchronous block, but actually executed in async way

Difference between Corutine and Thread

both corutine and thread can achieve async works

for this point, they are the same, corutine can be regard as light-weight thread

but in fact, corutine is more a programming pattern, it cares how to write code easily

while thread is a hardware concept, it cares how cpu really works in concurrent situation

multiple corutines can run on same thread, also can run on different threads

corutines emphase how to write async code, while threads emphase the actual performance

corutines depend on threads, but it simplify traditional async programming with thread apis

Fast Usage

launch start a corutine to handle async work

step 2 will output before step 1 , because coroutine will not block code in host

import kotlinx.coroutines.*suspend fun main() {GlobalScope.launch {delay(1000L)println("step 1")}println("step 2")delay(999*1000L)
}

async start a corutine that have a return value

the return value which called deferred , can be used in other corutine

step 1 will output before step 2 this time, as corutine 2 will wait result of corutine 1

step 3 will still output before step 1

import kotlinx.coroutines.*suspend fun main() {val deferred = GlobalScope.async {delay(5000L)println("step 1")return@async 100}GlobalScope.launch {println("step 2 ${deferred.await()}")}println("step 3")delay(99000L)
}
Suspend Function

from demos above, we can see a keyword called suspend

suspend means that this function can hang up, and continue handling work in another place

suspend function can only be called from coroutine block, or other suspend functions

because only coroutine has the ability to suspend and resume, normal functions was not able to do this

behavior contrary to suspend is resume , which is often hidden under the mask of coroutines framework

Advanced Usage of Coroutine

there are many variant forms to use coroutines

you can launch a coroutine using kotlinx.coroutines library like this

import kotlinx.coroutines.*suspend fun main() {val parentJob = Job()val scope = CoroutineScope(parentJob)val dispatcher = Dispatchers.Defaultval start = CoroutineStart.LAZYval job = scope.launch(dispatcher, start) {println("coroutine by launch")}job.start()delay(999*1000L)
}
Coroutine Essentials

a coroutine contains may composed of many essentials

now, let’s introduce them one by one, please take patience here

  • CoroutineContext : all essentials that determine how coroutine works
  • CoroutineScope : offer a scope of current coroutine, determine which coroutine you are writting in
  • CoroutineDispatcher : decide which thread coroutine work on
  • CoroutineStart : decide when to execute coroutine block
  • CoroutineExceptionHandler : how to handle exception when error occurs
  • ContinuationInterceptor : intercept current coroutine, and create a new coroutine based on current
  • most common implementation of ContinuationInterceptor is CoroutineDispatcher
  • Job : present the task that coroutine handles, can be cancelled manually
  • CoroutineName : give a name for current coroutine
CoroutineContext

CoroutineContext is the base class of most coroutine essential instances

coroutine context can be a single essential, or a collection of multiple essentials

context can be a standalone essential, also can hold some child essentials

likes a data struct below

class Context : Map<Key, Context>

a coroutine context can be added to another context, then form a new context contains both of them

if key is not contained in current context, add it, otherwise, replace it

val newCoroutineContext = currentContext + contextItem

coroutine essentials can be obtained from context through specific key

val job = context[Job]
val name = context[CoroutineName]
val dispather = context[CoroutineDispatcher]
val interceptor = context[ContinuationInterceptor]
val errorHandler = context[CoroutineExceptionHandler]

CoroutineContext has a direct child interface called CoroutineContext.Element

most classes are directly inherited from Element but not Context

they are actually the same thing

but Element emphas the class is intented to resolve specific requirement, not act as a collection

CoroutineScope

coroutine scope hold a coroutine context object named coroutineContext

coroutineContext holds all essentials for current coroutine

design intents of CoroutineScope can cover two aspects

  • hide internal functions of actual CoroutineImpl
  • offer a block scope object to control current coroutine

coroutine scope can be cancelled, when scope is cancelled, coroutine is cancelled

in fact, coroutine scope cancell coroutine by delegate object obtained from coroutineContext[Job]

Predefined CoroutineScope
  • GlobalScope

    an empty scope, cannot be cancelled, always available

  • LifecycleScope

    bind with android LifecycleOwner, when lifecycle is destroyed, scope will be cancelled

  • ViewModelScope

    bind with android ViewModel, when ViewModel is cancelled, scope will be cancelled

Predefined Dispatchers
  • Dispatchers.Default

    post to default thread pool, designed to handle computation work

  • Dispatchers.IO

    post to default thread pool, designed to handle computation work

  • Dispatchers.Main

    post to ui thread, designed to handle ui work, implementation depend on platform adapter

  • Dispatchers.Unconfined

    not change thread, execute immediately

there are some details we should concern

  • Dispatchers.Default and Dispatchers.IO share the same thread pool

    but each thread has a flag, to indicate whether receive cpu-intensive-work or memory-intensive-work

  • when Dispatchers.Unconfined is continuously used in child coroutines

    tasks will be post to event loop queue, maintained in current thread, to avoid StackOverflow error

Predefined CoroutineStart

CoroutineStart define the start strategy of coroutines

before introduce of those strategies, let’s understand differences between dispatch and execute first

execute means coroutine block is executed

dispatch means coroutine block is post to thread or task queue, but not executed yet

execute always happens behind dispatch

  • CoroutineStart.DEFAULT

    dispatched immediately, can be cancelled before dispatch

  • CoroutineStart.ATOMIC

    dispatched immediately, but cannot be cancelled until block suspended

  • CoroutineStart.LAZY

    not dispatched, until start api is actively called, such as start join await

  • CoroutineStart.UNDISPATCHED

    executed immediately in current calling-stack, not dispatched, until block’s first suspend

CoroutineStart.DEFAULT and CoroutineStart.LAZY are the most common ways

while CoroutineStart.ATOMIC and CoroutineStart.UNDISPATCHED are design for special scenarios

Job

represent the task coroutine handles, returned when coroutine is created

can be used to start or cancel a coroutine, and query coroutine state

  • start : start coroutine
  • cancel : cancel coroutine
  • join : join another coroutine and wait completed
  • parent : get parent job
  • isCancelled : query whether coroutine is cancelled
  • isCompleted : query whether coroutine is completed
  • invokeOnCompletion : set cancel or complete callback
Create a Coroutine

kotlinx.coroutines framework offers several ways to create coroutines

  • CoroutineScope.launch

    create a coroutine, without blocking current calling stack

  • CoroutineScope.async

    create a coroutine, with a FutureResult called Deferred returned, not blocking current calling stack

    value in Deferred can be got by await, blocking current calling stack until value returned

  • withContext(CoroutineContext, CoroutineScope.() -> R)

    create a coroutine, with specified context, blocking current calling stack until block finished and value returned

  • CoroutineDispatcher.invoke(CoroutineScope.() -> R)

    create a coroutine, with specified dispatcher, blocking current calling stack until block finished and value returned

    in fact, this is a inline function, actually calls withContext(dispatcher, block)

  • runBlocking(CoroutineContext, CoroutineScope.() -> T)

    create a coroutine, with specified context, blocking until block finished and value returned

    this function will not only block calling stack, but also block current thread

    it is designed to use suspend-style apis in non-suspend functions

    only suggest using it in main function or unit test functions

  • coroutineScope(CoroutineScope.() -> R)

    create a coroutine based on current coroutine context, equivalent to withContext(coroutineContext, block)

  • supervisorScope(CoroutineScope.() -> R)

    like coroutineScope, but child coroutine’s exception won’t be delivered to parent coroutine

all coroutines will start automatically by default, unless you specify other start strategy

ContinuationInterceptor

interceptor can intercept current coroutine, and extend extra operations based on origin coroutine

taking Dispatcher as an example, it handles the same work as the origin coroutine, with a thread switch operation extended

CoroutineExceptionHandler

there are two chances can trigger exception

  • error occurs, and exception is thrown
  • error saved in result, and get result is called

there are several handlers can handle exception

  • exception handler from parent coroutine
  • exception handler from current coroutine
  • exception handler from thread

how exception deliver between coroutine depends on many factors

it is a complex subject, we will talk about it in next blog

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/461601.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue中如何为不同功能设置不同的默认打印设置(设置不同的打印机)

浏览器自带的window.print 功能较简单&#xff0c;这里使用LODOP露肚皮打印 以下是vue2示例&#xff1a; 从官网中下载Lodop和C-Lodop官网主站安装包并安装到本地电脑可以全局搜索电脑找到安装文件LodopFuncs.js&#xff0c;也可以直接复制我贴出来的文件 //用双端口加载主JS…

数据库管理系统的ACID都各自是什么?

本文基于DBMS中ACID属性的概念&#xff0c;这些属性保证了数据库中执行事务时保持数据一致性、完整性和可靠性所。事务是访问并可能修改数据库内容的单一逻辑工作单元。交易使用读写操作访问数据。为了保持数据库的一致性&#xff0c;在事务前后&#xff0c;遵循某些属性。这些…

ssm基于vue搭建的新闻网站+vue

系统包含&#xff1a;源码论文 所用技术&#xff1a;SpringBootVueSSMMybatisMysql 免费提供给大家参考或者学习&#xff0c;获取源码请私聊我 需要定制请私聊 目 录 目 录 I 摘 要 III ABSTRACT IV 1 绪论 1 1.1 课题背景 1 1.2 研究现状 1 1.3 研究内容 2 [2 系统…

OB_GINS_day3

这里写目录标题 实现当前状态初始化实现预积分的初始化由于此时preintegration_options 是3&#xff08;也就是考虑odo以及earth rotation&#xff09;为预积分的容器添加需要积分的IMU积分因子接下来是添加新的IMU到preintegration中 实现当前状态初始化 这个state_curr的主要…

如何优化kafka和mysql处理百万级消息计算和落库

一.业务场景 最近业务需要&#xff0c;做了性能优化操作。百万级消息在kafka中秒级传输。cpu密集计算分钟级完成&#xff0c;然后在mysql中秒级落库.模型cpu计算提高了1倍&#xff0c;落表速度提高了5倍&#xff0c;2分钟内完成. 如下序列图&#xff1a; 业务系统A发送千级别…

深度学习基础知识-Batch Normalization(BN)超详细解析

一、背景和问题定义 在深层神经网络&#xff08;Deep Neural Networks, DNNs&#xff09;中&#xff0c;层与层之间的输入分布会随着参数更新不断发生变化&#xff0c;这种现象被称为内部协变量偏移&#xff08;Internal Covariate Shift&#xff09;。具体来说&#xff0c;由…

NLP算法工程师精进之路:顶会论文研读精华

1.学术能力培养 全部论文资料下载&#xff1a; 将论文和 GitHub 资源库匹配 papers with code https://paperswithcode.com/OpenGitHub 新项目快报Github pwc&#xff1a;https://github.com/zziz/pwc GitXiv&#xff1a;http://www.gitxiv.com/ 文章撰写 Overleaf [Autho…

从倍压整流到二极管钳位与限幅

何为倍压整流&#xff1f;这里直接引用“百度百科”解释&#xff0c;如下述。 在一些需用高电压、小电流的地方&#xff0c;常常使用倍压整流电路。倍压整流&#xff0c;可以把较低的交流电压&#xff0c;用耐压较高的整流二极管和电容器&#xff0c;“整”出一个较高的直流电…

Java项目实战II基于Java+Spring Boot+MySQL的工程教育认证的计算机课程管理平台(源码+数据库+文档)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 随着工程教…

uniapp开发小程序【简单的实现点击下拉选择性别功能】

一、展示效果 二、代码 <template><view><view class="form_box"><view class="item"

硅谷甄选(9)SKU模块

SKU模块 8.1 SKU静态 <template><el-card><el-table border style"margin: 10px 0px"><el-table-column type"index" label"序号" width"80px"></el-table-column><el-table-columnlabel"名称…

Flutter Color 大调整,需适配迁移,颜色不再是 0-255,而是 0-1.0,支持更大色域

在之前的 3.10 里&#xff0c; Flutter 的 Impeller 在 iOS 上支持了 P3 广色域图像渲染&#xff0c;但是当时也仅仅是当具有广色域图像或渐变时&#xff0c;Impeller 才会在 iOS 上显示 P3 的广色域的颜色&#xff0c;而如果你使用的是 Color API&#xff0c;会发现使用的还是…

动态威胁场景下赋能企业安全,F5推出BIG-IP Next Web应用防火墙

许多企业正面临由混合和多云环境运营复杂性所引发的危机&#xff0c;它们普遍耗巨资于物理和虚拟设备的持续维护、修补和升级上&#xff0c;而针对不同云环境下的应用部署则需要特有的技能来管理众多繁杂的工具和服务。为助力企业应对上述挑战&#xff0c;F5公司发布了BIG-IP N…

如何用Python同时抓取多个网页:深入ThreadPoolExecutor

背景介绍 在信息化时代&#xff0c;数据的实时性和获取速度是其核心价值所在。对于体育赛事爱好者、数据分析师和投注行业而言&#xff0c;能否快速、稳定地抓取到实时比赛信息显得尤为重要。特别是在五大足球联赛中&#xff0c;能够在比赛进行时获得比分、控球率等实时数据&a…

(转载)Tools for Learning LLVM TableGen

前提 最近在学习有关llvm的东西&#xff0c;其中TableGen占了一部分&#xff0c;所以想特意学习下TableGen相关的语法。这里找到了LLVM官网的一篇介绍TableGen的博客&#xff0c;学习并使用机器翻译为中文。在文章的最后也添加了一些学习TableGen的资源。 原文地址&#xff1…

LARGE SCALE GAN TRAINING FORHIGH FIDELITY NATURAL IMAGE SYNTHESIS

ABSTRACT 尽管最近在生成图像建模方面取得了进展&#xff0c;但成功地从复杂的数据集(如ImageNet)生成高分辨率、多样化的样本仍然是一个难以实现的目标。为此&#xff0c;我们在迄今为止尝试的最大规模上训练生成对抗网络&#xff0c;并研究这种规模特有的不稳定性。我们发现…

组队学习专用——task05

目录 一、基本原理 1. 决策树的基本思想 2. 决策树划分过程中可能遇到的特殊情况 (1) 单一类别终止&#xff1a; (2) 属性用尽&#xff1a; (3) 样本空缺&#xff1a; 3. 决策树的结构 二、信息量、信息熵 1. 信息量 2. 信息熵 三、决策树 1. ID3 决策树&#xff08…

Linux RAID 技术详解:原理、配置、管理及故障处理

本文档深入探讨 Linux 软件 RAID 技术&#xff0c;涵盖 RAID 原理、各种 RAID 级别、mdadm 命令详解、配置步骤、管理方法以及高级故障处理和性能调优策略。 一、 RAID 原理与架构 RAID (Redundant Arrays of Independent Disks&#xff0c;独立磁盘冗余阵列) 技术并非单一技…

「C/C++」C/C++标准库 之 <cstring> 字符串操作库

✨博客主页何曾参静谧的博客📌文章专栏「C/C++」C/C++程序设计📚全部专栏「VS」Visual Studio「C/C++」C/C++程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasolid函数说明目…

单细胞数据分析(一):10X数据生成seurat数据对象

文章目录 介绍加载R包数据链接导入数据过滤细胞:移除双重细胞合并所有seurat数据对象输出结果系统信息介绍 在单细胞基因组学研究中,Seurat是一个流行的R包,用于单细胞基因表达数据的分析和探索。以下是如何从10X基因注释数据生成Seurat数据对象,并对该数据进行过滤的步骤…