
Kotlin语言基础入门到熟悉Kotlin协程基础1. 阻塞与非阻塞runBlockingdelay是非阻塞的Thread.sleep是阻塞的。显式使用runBlocking协程构建器来阻塞。importkotlinx.coroutines.\*funmain(){GlobalScope.launch{// 在后台启动一个新的协程并继续delay(200)rustfisher.com.forEach{print(it)delay(280)}}println(主线程中的代码会立即执行)runBlocking{// 这个表达式阻塞了主线程delay(3000L)//阻塞主线程防止过快退出}println(\n示例结束)}可以看到runBlocking里使用了delay来延迟。用了runBlocking的主线程会一直阻塞直到runBlocking内部的协程执行完毕。 也就是runBlocking{ delay }实现了阻塞的效果。我们也可以用runBlocking来包装主函数。importkotlinx.coroutines.\*funmain()runBlocking{delay(100)// 在这里可以用delay了GlobalScope.launch{delay(100)println(Fisher)}print(Rust )delay(3000)}runBlockingUnit中的Unit目前可以省略。runBlocking也可用在测试中// 引入junitdependencies{implementation(junit:junit:4.13.1)}单元测试使用Test设置测试importorg.junit.Testimportkotlinx.coroutines.\*classC3Test{Test funtest1()runBlocking{println(junit测试开始 ${System.currentTimeMillis()})delay(1234)println(junit测试结束 ${System.currentTimeMillis()})}}运行结果junit测试开始1632401800686junit测试结束1632401801928IDEA可能会提示no tasks available。需要把测试选项改为IDEA如下图。更改设置2. 等待有时候需要等待协程执行完毕。可以用join()方法。这个方法会暂停当前的协程直到执行完毕。需要用main() runBlocking。importkotlinx.coroutines.\*funmain()runBlocking{println(测试等待)val job1GlobalScope.launch{println(job1 start)delay(300)println(job1 done)}val job2GlobalScope.launch{println(job2 start)delay(800)println(job2 done)}job2.join()job1.join()// 等待println(测试结束)}运行log测试等待 job1 start job2 start job1 done job2 done 测试结束3. 结构化的并发用GlobalScope.launch时会创建一个顶层协程。它不使用主线程。新创的协程虽然轻量但仍会消耗一些内存资源。如果忘记保持对新启动的协程的引用它还会继续运行。我们可以在代码中使用结构化并发。示例中我们使用runBlocking协程构建器将main函数转换为协程。在里面作用域启动的协程不需显式使用join。观察下面的例子importkotlinx.coroutines.\*funmain()runBlockingUnit{println(主线程id ${Thread.currentThread().id})launch{// 在 runBlocking 作用域中启动一个新协程1println(协程1所在线程id ${Thread.currentThread().id})delay(300)println(协程1执行完毕)}launch{// 在 runBlocking 作用域中启动一个新协程2println(协程2所在线程id ${Thread.currentThread().id})delay(500)println(协程2执行完毕)}println(主线程执行完毕)}运行log主线程id1主线程执行完毕 协程1所在线程id1协程2所在线程id1协程1执行完毕 协程2执行完毕可以看到不用像之前那样调用Thread.sleep或者delay让主线程等待一段时间防止虚拟机退出。程序会等待它所有的协程执行完毕然后真正退出。4. 作用域构建器使用coroutineScope构建器声明自己的作用域。它会创建一个协程作用域并且会等待所有已启动子协程执行完毕。runBlocking与coroutineScope看起来类似因为它们都会等待其协程体以及所有子协程结束。主要区别在于*runBlocking方法会阻塞当前线程来等待是常规函数*coroutineScope只是挂起会释放底层线程用于其他用途是挂起函数下面这个示例展示了作用域构建器的特点。main是一个作用域。importkotlinx.coroutines.\*funmain()runBlocking{// this: CoroutineScopelaunch{delay(200L)println(协程1 t${Thread.currentThread().id})}coroutineScope{// 创建一个协程作用域launch{delay(500L)println(内部协程2-1 t${Thread.currentThread().id})}delay(100L)println(协程2 t${Thread.currentThread().id})}println(主任务完毕)}运行log协程2t1 协程1t1 内部协程2-1t1 主任务完毕5. 提取函数重构将launch { …… }内部的代码块提取到独立的函数中。提取出来的函数需要suspend修饰符它是挂起函数。importkotlinx.coroutines.delayimportkotlinx.coroutines.launchimportkotlinx.coroutines.runBlocking funmain()runBlockingUnit{launch{r1()}println(DONE)}// 挂起函数suspend funr1(){delay(300)println(提取出来的函数)}logDONE提取出来的函数6. 协程是轻量的我们前面也试过创建非常多的协程程序运行OK。下面的代码可以输出很多的点importkotlinx.coroutines.\*funmain()runBlocking{for(tin1..10000){launch{delay(t \*500L)print(.)}}}7. 全局协程像守护线程如果进程中只剩下了守护线程那么虚拟机会退出。 前文那个的例子其实也能看到字符没打印完程序就结束了。在GlobalScope中启动的活动协程并不会使进程保活。它们就像守护线程。再举一个例子importkotlinx.coroutines.\*funmain()runBlocking{GlobalScope.launch{for(iin1..1000000){delay(200)println(协程执行: $i)}}delay(1000)println(Bye~)}log协程执行:1协程执行:2协程执行:3协程执行:4Bye~最后分享一份【腾讯技术团队出品】Android零基础入门到精通Android Studio安装教程全套安卓基础教程Android编程入门教程Java语言基础从入门到熟悉Kotlin语言基础从入门到熟悉Android 技术栈从入门到熟悉Android Jetpack 全家桶全面学习对于新手来说可能安装Android Studio存在一定困难你可以看着以下视频一步步的跟着学习安装运行Android Studio 安装教程有了Java阶段的学习这一阶段建议以视频学习为主辅以图书查漏补缺。如果以图书为主可以根据图书讲解敲代码辅以教学视频查漏补缺。遇到问题可以去百度入门的问题一般会有很多人遇到并且给出比较好的解答。需要掌握基本知识点比如四大组件如何使用、如何创建Service、如何进行布局、简单的自定义View、动画、网络通信等常见技术。全套零基础教程已经为你们准备好了需要的可以添加下方二维码免费领取全套安卓基础教程