Kotlin开发利器之协程

协程的定义

  协程的开发人员 Roman Elizarov 是这样描述协程的:协程就像非常轻量级的线程。线程是由系统调度的,线程切换或线程阻塞的开销都比较大。而协程依赖于线程,但是协程挂起时不需要阻塞线程,几乎是无代价的,协程是由开发者控制的。所以协程也像用户态的线程,非常轻量级,一个线程中可以创建任意个协程。

项目中引入Kotlin的协程

  添加依赖:coroutines库在Kotlin1.3版本的时候已经升级为正式版,命名为1.0.0。

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.0.0'
// 可以添加Android的依赖
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.0'

1.协程方法的开启

GlobalScope.launch

fun main(args: Array<String>) {GlobalScope.launch { // 在后台启动一个新的协程并继续delay(1000L) // 非阻塞线程1sprintln("World!") // 在延迟后打印输出println("This is a coroutines ${TimeUtil.getTimeDetail()}")}println("Hello,") // 主线程的协程将会继续等待Thread.sleep(2000L) // 阻塞线程2s,保证JVM存活,协程可正常执行完println("main end ${TimeUtil.getTimeDetail()}")
}// 输出
// Hello,
// World!
// This is a coroutines 10:49:58
// main end 10:49:59

在线程环境中可直接使用CoroutineScope.launch启动一个新的协程,它的参数有如下三个,分别为:

  • context: CoroutineContext = EmptyCoroutineContext:协程上下文;
  • start: CoroutineStart = CoroutineStart.DEFAULT:启动模式,默认是DEAFAULT,也就是创建就启动;还有一个是LAZY,意思是等你需要它的时候,再调用启动。在Kotlin 1.3版本中,还有ATOMIC和UNDISPATCHED两个额外的模式,但是现在还是实验版,这里不多介绍;
  • block: suspend CoroutineScope.() -> Unit:闭包参数,定义协程内需要执行的操作。

  返回值为Job对象。Job有如下几个重要的方法,分别为:
  job.start()可配合LAZY启动一个协程

fun main(args: Array<String>){val job = GlobalScope.launch(start = CoroutineStart.LAZY) {println("this is a job")}job.start()Thread.sleep(1000L)
}// 输出
// this is a job

  job.join()等待协程执行完毕

suspend fun main(args: Array<String>){val job = GlobalScope.launch {println("this is a job")}job.join()
}// 输出
// this is a job

  注意:join()函数是一个挂起函数,所有main必须被suspend修饰。
  job.cancel()取消一个协程

suspend fun main(args: Array<String>){val job = GlobalScope.launch {println("this is a job")}job.cancel()job.join()
}// 无输出,协程被取消了

  job.cancelAndJoin()等待协程执行完毕然后再取消

suspend fun main(args: Array<String>){val job = GlobalScope.launch {println("this is a job")}job.cancelAndJoin()
}// 输出
// this is a job

  job.cancelAndJoin()也是一个挂起函数。
  从上面的代码和输出可以看到,协程中的输出和main中的输出只相差了1s,也就说明了为什么delay(1000L)是非阻塞的。delay()函数类似于Thread.sleep(),但是它不阻塞(non-blocking)线程,它是一个被suspend修饰的挂起函数,挂起函数只能被挂起函数调用或协程中调用。

2.GlobalScope.async

suspend fun main(args: Array<String>) {val deferred = GlobalScope.async {delay(1000L)println("This is async ${TimeUtil.getTimeDetail()}")return@async "taonce"}println("main start ${TimeUtil.getTimeDetail()}")val result = deferred.await()println("async result is $result")println("main end ${TimeUtil.getTimeDetail()}")
}
// 输出
// main start 15:27:19:668
// This is async 15:27:20:652
// async result is taonce
// main end 15:27:20:657

  async和launch参数是一模一样的,不同的是async返回的是Deferred对象,它继承了Job接口,所以说Job有的它都有,并且还额外增加了一个方法:
public suspend fun await(): T这个方法接收的是async闭包中返回的值。如果闭包中需要返回一个值那么我们就需要考虑用async了。

3.runBlocking

  runBlocking的最大特点就是它的delay()可以阻塞当前的线程,和Thread.sleep()有着相同的效果。一般用runBlocking来桥接普通阻塞代码和挂起风格的非阻塞代码,在runBlocking闭包里面启动另外的协程。

协程实际运用

  以最常用的网络请求为例,如果不用Kotlin的协程来实现,我们可以用Thread、RxJava等等很多种方法。

class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)coroutine.setOnClickListener { click() }}private fun click() = runBlocking {GlobalScope.launch(Dispatchers.Main) {coroutine.text = GlobalScope.async(Dispatchers.IO) {// 比如进行了网络请求// 放回了请求后的结构return@async "main"}.await()}}
}

  上面代码的原理是:用async()在IO线程中去执行网络请求,然后通过await()返回请求结果,最后用launch(Dispatchers.Main)在主线程中更新UI。
  其中用到了Dispatchers来指定协程所在的线程,目前Dispatchers有三种:

  • Default:如果没有指定具体的Dispatchers都会使用默认的,它使用的是最大的线程数;
  • IO:用来调度阻塞的协程;
  • Main:就是常说的UI线程了,是Android特有的。

总结

  • 本质上,协程是轻量级的线程;
  • 挂起函数(被suspend修饰的函数)不能在普通函数中被调用;
  • 可以使用一些协程操作来替换一些线程操作,比如: 用 GlobalScope.launch { …… } 替换 thread { …… } 用 delay(……) 替换 Thread.sleep(……);
  • 协程是轻量级的,比开启线程节约资源;
  • 在 GlobalScope 中启动的活动中的协程就像守护线程一样,不能使它们所在的进程保活。

Kotlin开发利器之协程相关推荐

  1. 《Kotlin 程序设计》第十二章 Kotlin的多线程:协程(Coroutines)

    第十二章 Kotlin的多线程:协程(Coroutines) Kotlin 1.1 introduced coroutines, a new way of writing asynchronous, ...

  2. Kotlin学习笔记26 协程part6 协程与线程的关系 Dispatchers.Unconfined 协程调试 协程上下文切换 Job详解 父子协程的关系

    参考链接 示例来自bilibili Kotlin语言深入解析 张龙老师的视频 1 协程与线程的关系 import kotlinx.coroutines.* import java.util.concu ...

  3. Kotlin学习笔记25 协程part5 协程的同步与异步

    参考链接 示例来自bilibili Kotlin语言深入解析 张龙老师的视频 1 程序运行时间统计measureTimeMillis /*** 程序运行时间统计measureTimeMillis** ...

  4. Kotlin Jetpack 实战: 图解协程原理 | 开发者说·DTalk

    本文原作者: 朱涛,原文发布于: 朱涛的自习室 https://mp.weixin.qq.com/s/fN4cSg6jcFZo3Wb2_xcJVw 协程 (Coroutines),是 Kotlin「最 ...

  5. Kotlin学习笔记24 协程part4 协程的取消与超时

    参考链接 示例来自bilibili Kotlin语言深入解析 张龙老师的视频 1 如何取消协程 import kotlinx.coroutines.*/*** 协程的取消*/fun main() = ...

  6. Kotlin学习笔记23 协程part3 lambda表达式深入 挂起函数 全局协程

    参考链接 示例来自bilibili Kotlin语言深入解析 张龙老师的视频 1 lambda表达式深入 /*** lambda 表达式深入* 当函数参数是函数时 并且该函数只有一个参数 可以不传入任 ...

  7. Kotlin学习笔记22 协程part2 join CoroutineScope 协程vs线程

    参考链接 示例来自bilibili Kotlin语言深入解析 张龙老师的视频 1 Job的join方法 import kotlinx.coroutines.* /*** Job的join方法* 它会挂 ...

  8. Kotlin学习笔记21 协程part1 基本概念

    参考链接 示例来自bilibili Kotlin语言深入解析 张龙老师的视频 本节先介绍协程的相关概念 概念可能枯燥,我们先要了解协程中的相关概念 然后结合代码理解这些概念 加深印象 协程的定义 协程 ...

  9. Kotlin(android)协程中文翻译

    1.官方文档地址 github.com/Kotlin/kotl- 2. 协程的配置 compile "org.jetbrains.kotlinx:kotlinx-coroutines-and ...

最新文章

  1. 身为DATASHUO大数据工程师,我亲手制作的2016年第一期数据报告
  2. ADC知识(2)——直流参数(输入电压参考,参考电流输入,积分非线性误差,差分非线性误差)...
  3. 应届生怒怼管理层后续:已离职、被标记永不录用?腾讯张军回应...
  4. Hug a developer today
  5. zmq源码阅读 --- api介绍 -- zmq_ctx_new + zmq_socket + zmq_bind + zmq_close + zmq_ctx_destroy
  6. 软件工程~~判定树和判定表
  7. Adobe Flash Player 不是最新版本
  8. Uncaught TypeError: $(...).modal is not a function
  9. win系统设置定时开机
  10. keras model weights
  11. 嵌入式Linux设备驱动程序开发指南18(IIO子系统(二)具有硬件触发功能的IIO子系统ADC模块)——读书笔记
  12. 《Android深度探索卷一》读书笔记六
  13. php一句话论坛,PHP一句话
  14. ios html5 audio mp3,H5 audio 微信端 在IOS上不能播放音乐
  15. 信鸽推送-10005错误
  16. 如何将Asp.net 2.0网站部署到服务器
  17. python code for solving eigenvalue problem by Jacobi’s method的代码
  18. 1D Barcode图片组件,支持线性和邮政符号
  19. Python爬虫实战项目:简单的百度新闻爬虫
  20. 从威客到互联网进化论的五年历程

热门文章

  1. 腾讯企业邮箱只能接受消息不能发送
  2. 更改sendmail附件大小限制
  3. Stm32f407zgt6 143引脚PDR_ON 的注意事项
  4. 创业者自述:都2020年了,我为什么还在做翻盖手机?
  5. Shiro 实战教程(全)
  6. 今天的天气是多么的晴朗
  7. 【解题】核电站问题(SGOI)
  8. 【医学信息学】研究和统计——队列研究和数据分析
  9. 开关电源拓扑结构详解
  10. 【Lilishop商城】No3-3.模块详细设计,会员信息(会员基本信息)、店铺设置(店铺信息、配送模板)的详细设计