Kotlin基础——异步和并发
同步和异步
- 同步指的是一种行为:当执行IO操作的时候,在代码层面上我们需要主动去等待结果,直到结果返回
- 阻塞指的是一种状态:当执行IO操作的时候,线程处于挂起状态,就是该线程没有执行了
故同步不是阻塞,同步也可以是非阻塞的,如在执行同步代码块时,线程可以不阻塞而是一直在后台运行
代码中一般通过和多线程和回调来实现异步非阻塞
但多线程只是看上去同时执行,底层原理是通过CPU调度来实现的,当一个线程切换到另一个线程时,通常需要
- 保存当前线程的执行上下文
- 载入另一个线程的执行上下文
切换线程也是需要开销的,故当线程切换很频繁时,可能会导致多线程并不优于单线程
协程Coroutine
大量回调会使代码更加复杂,且会存在多层次的回调,同时线程切换的开销不可忽略,而协程则可以避免这些问题
协程是一个无优先级的子程序调度组件,允许子程序在特定的地方挂起恢复
- 进程包含线程,线程包含协程
- 一个线程可以有任意多个协程
- 某一时刻只能由一个协程在运行,多个协程分享该线程分配到的计算机资源
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.1"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1"
使用Coroutine需要导入包,如下通过launch构造了一个协程,通过delay()挂起协程,但不会阻塞线程
GlobalScope.launch {delay(1000L)println("World")
}
println("Hello, ")
Thread.sleep(2000L)
线程是由操作系统来调度的,而协程的切换可以由程序自己来控制,协程可以创建很多个,而线程是有限的
launch和runBlocking
- delay只能在协程内部使用,用于挂起协程,不会阻塞线程
- sleep用来阻塞线程
未避免混淆,可以使用runBlocking创建主协程,而使用launch创建子协程,从而在内部都使用delay(),但需要注意,runBlocking依旧会阻塞当前执行的线程
fun test() = runBlocking {GlobalScope.launch {delay(1000L)println("World")}println("Hello, ")delay(2000L)
}
协程声明周期和join
当执行耗时操作,但并不知道需要多久时,为使程序一直保活,可以使用join
- 如下程序会一直等待,直到协程结束,这里的等待是非阻塞式,不会将当前线程挂起
- suspend修饰的方法只能在协程内部或其他suspend方法中使用
fun test() = runBlocking {val job = launch {search()}println("Hello,")job.join()
}suspend fun search() {delay(1000L)println("World")
}
用同步方式写异步代码
在下面代码中,两个方法是顺序执行的
fun test() = runBlocking<Unit> {val one = searchOne()val two = searchTwo()println("search is ${one} and ${two}")
}suspend fun searchOne() {delay(3000L)println("one")
}suspend fun searchTwo() {delay(1000L)println("two")
}
打印如下
one
two
search is kotlin.Unit and kotlin.Unit
为了让其并行执行,可以使用async和await
- 使用async相当于创建了一个子协程,会和其他子协程一样并行工作
- async返回Deferred,是一个非阻塞可取消的future,其是一个带有结果的job,而Launch也会返回一个job但无返回值
- future的意思是将来会返回一个结果,利用await可以等待返回值查询到之后获取出来
fun test() = runBlocking<Unit> {val one = async { searchOne() }val two = async { searchTwo() }println("search is ${one.await()} and ${two.await()}")
}
打印如下
one
two
search is kotlin.Unit and kotlin.Unit
共享资源控制
锁
如对于下面的数据
val goods = hashMapOf<Long, Int>()
goods.put(1, 10)
goods.put(2, 15)
Synchronized
使用@Synchronized或synchronized()实现加锁
@Synchronized
fun buyGoods(id: Long) {val stock = goods.getValue(id)goods.put(id, stock - 1)
}
fun buyGoods2(id: Long) {synchronized(this) {val stock = goods.getValue(id)goods.put(id, stock - 1)}
}
Lock
var lock: Lock = ReentrantLock()
fun buyGoods3(id: Long) {lock.lock()try {val stock = goods.getValue(id)goods.put(id, stock - 1)} catch (ex: Exception) {println(ex)} finally {lock.unlock()}
}
上面写法有以下问题:
- 若有多个同步方法,将会竞争同一把锁
- 加锁后可能忘记解锁
- 重复的模板代码
fun <T> withLock(lock: Lock, action: () -> T) {lock.lock()try {action()} catch (ex: Exception) {println(ex)} finally {lock.unlock()}
}
fun buyGoods(id: Long) {val stock = goods.getValue(id)goods.put(id, stock - 1)
}
var lock: Lock = ReentrantLock()
withLock(lock, { buyGoods(1) })
上面使用高阶函数进行了优化,库函数也自带withLock()方法
fun buyGoods(id: Long) {val stock = goods.getValue(id)goods.put(id, stock - 1)
}
var lock: Lock = ReentrantLock()
lock.withLock({ buyGoods(1) })
相关文章:
Kotlin基础——异步和并发
同步和异步 同步指的是一种行为:当执行IO操作的时候,在代码层面上我们需要主动去等待结果,直到结果返回阻塞指的是一种状态:当执行IO操作的时候,线程处于挂起状态,就是该线程没有执行了 故同步不是阻塞&a…...
消防认证-防火卷帘
一、消防认证 消防认证是指消防产品符合国家相关技术要求和标准,且通过了国家认证认可监督管理委员会审批,获得消防认证资质的认证机构颁发的证书,消防产品具有完好的防火功能,是住房和城乡建设领域验收的重要指标。 二、认证依据…...
SpringBoot3.3集成knif4j-swagger文档方式和使用案例
springboot3 集成 knif4j : 访问地址: swagger 接口文档默认地址:http://localhost:8080/swagger-ui.html# Knife4j 接口文档默认地址:http://127.0.0.1:8080/doc.html Maven: <dependency><groupId>com.github.x…...
老年服务与管理实训室:制定教学模式
随着我国人口老龄化程度的加深,如何为老年人提供优质的养老服务成为社会关注的重点。作为培养老年服务人才的重要阵地,老年服务与管理实训室应制定科学合理的教学模式,满足行业发展需求,培养出高素质的老年服务专业人才。本文针对老年服务与管理实训室的教学模式展开探讨,提出相…...
4、DDD、中台和微服务的关系
DDD、中台和微服务的关系 1 DDD和中台的本质 领域驱动设计(DDD)和中台在企业架构中有着密切的关系。DDD的本质在于通过对业务领域的深入分析和建模,构建高内聚、低耦合的系统。而中台则是对企业核心业务能力的抽象和封装,以实现…...
【ACM出版,马来西亚-吉隆坡举行】第四届互联网技术与教育信息化国际会议 (ITEI 2024)
作为全球科技创新大趋势的引领者,中国不断营造更加开放的科技创新环境,不断提升学术合作的深度和广度,构建惠及各方的创新共同体。这是对全球化的新贡献,是构建人类命运共同体的新贡献。 第四届互联网技术与教育信息化国际学术会议…...
走进IT的世界
引言 随着高考的结束,对于即将踏入IT(信息技术)领域的新生而言,这个假期不仅是放松身心的时间,更是提前规划、深化专业知识、为大学生活奠定坚实基础的宝贵机会。以下是一份详尽的高考假期预习与规划指南,…...
Linux 时区文件编译器 zic【man 8 zic】
1. NAME(名) zic - 时区编译器 2. SYNOPSIS(概要) zic [-v] [-d directory] [-l localtime] [-p posixrules] [-L leapsecondfilename] [-s] [-y command] [filename ...]3. DESCRIPTION(函数描述) zic…...
Springboot下使用Redis管道(pipeline)进行批量操作
之前有业务场景需要批量插入数据到Redis中,做的过程中也有一些感悟,因此记录下来,以防忘记。下面的内容会涉及到 分别使用for、管道处理批量操作,比较其所花费时间。 分别使用RedisCallback、SessionCallback进行Redis pipeline …...
Vue技巧大揭秘:自定义指令的力量与应用
引言 自定义指令就像是给予开发者的一把魔法钥匙,它能够打开DOM操作的新世界,按我的理解就是把对DOM操作的逻辑进行封装 全局注册与局部注册 全局注册 定义: 全局注册意味着自定义指令在Vue实例创建之前通过Vue.directive()方法注册&…...
HR人才测评,如何考察想象力?
什么是想象力? 想象力是指,人们通过在已有物质的基础上,通过大脑想象、加工、创造出新事物的能力,举一个非常简单的例子,在提到鸟这种生活的时候,大家会联想到各种各样不同鸟的品种。 在企业招聘中常常应…...
Git命令远程分支的合并和本地分支的同步
天行健,君子以自强不息;地势坤,君子以厚德载物。 每个人都有惰性,但不断学习是好好生活的根本,共勉! 文章均为学习整理笔记,分享记录为主,如有错误请指正,共同学习进步。…...
墨烯的C语言技术栈-C语言基础-003
三.数据类型 1.char // 字符数据型 2.short // 短整型 3.int // 整型 4.long // 长整型 5.long long // 更长的整型 6.float // 单精度浮点数 7.double // 双精度浮点数 为什么写代码? 为了解决生活中的问题 购物,点餐,看电影 为什么有这么多类型呢? 因为说的话都是字符型…...
RpcRrovider分发rpc服务(OnMessage和Closure回调)
目录 1.完善rpcprovider.cc的OnConnection 2.完善rpcprovider.cc的OnMessage 3.完整rpcprovider.h 4.完整rpcprovider.cc 这篇文章主要完成,protobuf实现的数据序列化和反序列化。 1.完善rpcprovider.cc的OnConnection rpc的请求是短连接的,请求一次…...
分解+降维+预测!多重创新!直接写核心!EMD-KPCA-Transformer多变量时间序列光伏功率预测
分解降维预测!多重创新!直接写核心!EMD-KPCA-Transformer多变量时间序列光伏功率预测 目录 分解降维预测!多重创新!直接写核心!EMD-KPCA-Transformer多变量时间序列光伏功率预测效果一览基本介绍程序设计参…...
【Python】MacBook M系列芯片Anaconda下载Pytorch,并开发一个简单的数字识别代码(附带踩坑记录)
文章目录 配置镜像源下载Pytorch验证使用Pytorch进行数字识别 配置镜像源 Anaconda下载完毕之后,有两种方式下载pytorch,一种是用页面可视化的方式去下载,另一种方式就是直接用命令行工具去下载。 但是由于默认的Anaconda走的是外网&#x…...
自定义控件动画篇(四)ObjectAnimator的使用
ObjectAnimator 是 Android 属性动画框架中的一个重要组件,它允许你针对特定属性的值进行动画处理。与 ValueAnimator 相比,ObjectAnimator 更专注于 UI 组件,可以直接作用于视图的属性,如位置、尺寸、透明度等,而无需…...
实现List接口的ArrayList和LinkedList
package study;import java.util.*;public class day01_list {public static void main(String[] args) {// <Integer> 这个尖括号表示的是 Java 的泛型(Generics)// 泛型是 Java 5 引入的一项特性,它允许你在 类、接口和方法 中使用类…...
下拉选择输入框(基于elment-ui)
最近在需求中,需要有一个下拉选择功能,又得可以输入,在 element-ui 官网找了,发现没有适合的,然后在修炼 cv 大法的我,也在网上看了一下,但是也都感觉不合适,所以就自己写了两个&…...
CPP入门:日期类的构建
目录 1.日期类的成员 2.日期类的成员函数 2.1构造和析构函数 2.2检查日期合法 2.3日期的打印 2.4操作符重载 2.4.1小于号 2.4.2等于号 2.4.3小于等于号 2.4.4大于号 2.4.5大于等于号 2.4.6不等号 2.4.7加等的实现 2.4.8加的实现 2.4.9减去一个天数的减等实现 2.4.10…...
synchronized 学习
学习源: https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖,也要考虑性能问题(场景) 2.常见面试问题: sync出…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...
关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...
新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...
【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
【Linux手册】探秘系统世界:从用户交互到硬件底层的全链路工作之旅
目录 前言 操作系统与驱动程序 是什么,为什么 怎么做 system call 用户操作接口 总结 前言 日常生活中,我们在使用电子设备时,我们所输入执行的每一条指令最终大多都会作用到硬件上,比如下载一款软件最终会下载到硬盘上&am…...
Unity中的transform.up
2025年6月8日,周日下午 在Unity中,transform.up是Transform组件的一个属性,表示游戏对象在世界空间中的“上”方向(Y轴正方向),且会随对象旋转动态变化。以下是关键点解析: 基本定义 transfor…...
