• Kotlin 进阶版 协程


    kotlin是协程的一种实现

    1. Dispatchers.IO:适用于执行磁盘或网络 I/O 操作的调度器,例如文件读写、网络请求等。在 Android 中,Dispatchers.IO 会使用一个专门的线程池来处理这些操作,以防止阻塞主线程。

    2. Dispatchers.Main:适用于处理与 UI 相关的操作的调度器,例如更新 UI 界面、响应用户输入等。在 Android 中,Dispatchers.Main 通常会将协程切换到主线程执行,确保 UI 操作在主线程中进行。

    3. Dispatchers.Unconfined:不对协程的执行环境做任何限制,使用该调度器时,协程将在调用它的线程中执行,直到遇到挂起函数为止,之后会在恢复执行时继续在之前的线程中执行。

    4. Dispatchers.Default:适用于执行 CPU 密集型任务的调度器,例如算法计算、数据处理等。Dispatchers.Default 在 Android 中会使用一个共享的线程池来处理这些任务,以便在多个协程之间进行合理的调度。

     

    1. package com.tiger.kotlincoroutine.coroutine
    2. import kotlinx.coroutines.CoroutineScope
    3. import kotlinx.coroutines.Dispatchers
    4. import kotlinx.coroutines.delay
    5. import kotlinx.coroutines.launch
    6. import kotlinx.coroutines.withContext
    7. fun main() {
    8. //IO线程 超大密集的计算 Default
    9. /**
    10. * IO
    11. * Default
    12. * Main
    13. *
    14. */
    15. CoroutineScope(Dispatchers.IO).launch {
    16. test()
    17. // withContext(Dispatchers.Main){
    18. //
    19. // }
    20. }
    21. println("主线程")
    22. Thread.sleep(2000)
    23. }
    24. /**
    25. * 协程代码块
    26. */
    27. suspend fun test() {
    28. println("协程开始")
    29. delay(1000)
    30. println("协程结束")
    31. }

    1.runBlocking

    1. package com.tiger.kotlincoroutine.coroutine
    2. import kotlinx.coroutines.Dispatchers
    3. import kotlinx.coroutines.delay
    4. import kotlinx.coroutines.runBlocking
    5. fun main() {
    6. println("hello")
    7. //如果给的参数第一个为空,那么它会去找到这个协程外面调用它的这个线程 一般在写Test的时候才用一下 阻塞式协程
    8. val i = runBlocking (Dispatchers.IO){
    9. //如果制定了了调度器,它会被分配到另一个线程上面执行 ,但也可以阻塞当前线程
    10. println(
    11. Thread.currentThread().name
    12. )
    13. //这个协程会阻塞当前线程 同步执行
    14. delay(2000)
    15. 1
    16. }
    17. println(
    18. Thread.currentThread().name
    19. )
    20. println("world $i ")
    21. }

    1. package com.tiger.kotlincoroutine.coroutine
    2. import kotlinx.coroutines.Dispatchers
    3. import kotlinx.coroutines.delay
    4. import kotlinx.coroutines.launch
    5. import kotlinx.coroutines.runBlocking
    6. fun main() {
    7. println("hello")
    8. //如果给的参数第一个为空,那么它会去找到这个协程外面调用它调度器 一般在写Test的时候才用一下 阻塞式协程
    9. //会等里面所有的协程执行完了,才会释放主线程
    10. val i = runBlocking (Dispatchers.IO){
    11. //如果制定了了调度器,它会被分配到另一个线程上面执行 ,但也可以阻塞当前线程
    12. println(
    13. Thread.currentThread().name
    14. )
    15. println(this)
    16. //this :BlockingCoroutine 可以再次开启一个协程
    17. val job = this.launch {
    18. //这个开启的协程不会阻塞当前线程,异步
    19. println(
    20. //没有指定 ,他会默认继承上面所在的调度器 被这个调度器管理的线程池的线程去执行
    21. Thread.currentThread().name
    22. )
    23. delay(5200)
    24. }
    25. println(job.isActive)
    26. println(job.cancel())
    27. println(job.isActive)
    28. println("延迟了吗")
    29. //这个协程会阻塞当前线程 同步执行
    30. delay(2000)
    31. 1
    32. }
    33. println(
    34. Thread.currentThread().name
    35. )
    36. println("world $i ")
    37. /**
    38. * 总结
    39. * IO 网络请求 数据库
    40. * default 密集型数据处理操作 数据计算
    41. * main UI操作
    42. *
    43. */
    44. }

     

    1. package com.tiger.kotlincoroutine.coroutine
    2. import kotlinx.coroutines.Dispatchers
    3. import kotlinx.coroutines.delay
    4. import kotlinx.coroutines.runBlocking
    5. import kotlinx.coroutines.withContext
    6. fun main() {
    7. println("hello")
    8. val i = runBlocking (Dispatchers.IO){
    9. request{
    10. //手动切换到UI线程里
    11. withContext(Dispatchers.Main){
    12. //修改UI
    13. }
    14. }
    15. }
    16. println("world $i")
    17. }
    18. suspend fun request(finish:suspend ()->Unit){
    19. delay(3000)
    20. println("网络请求成功")
    21. finish()
    22. }

    好处:不会出现在其他的线程里出现UI报错的问题了

    2.GlobalScope

    1. package com.tiger.kotlincoroutine.coroutine
    2. import kotlinx.coroutines.GlobalScope
    3. import kotlinx.coroutines.delay
    4. import kotlinx.coroutines.launch
    5. fun main() {
    6. val launch = GlobalScope.launch { //全局指的是整个程序的生命周期 就算Activity销毁了这个GlobalScope还是存在的
    7. // 这样可能会造成一些奇怪的问题
    8. delay(3000)
    9. println("hello")
    10. }//这不是阻塞当前线程的一个协程操作
    11. val launch1 = GlobalScope.launch {
    12. }
    13. println(launch===launch1)
    14. //不能调用cancel 方法,因为作用域是整个生命周期的,不能由我们来管理
    15. while (true);
    16. }

    3.CoroutineScope

    1. package com.tiger.kotlincoroutine.coroutine
    2. import kotlinx.coroutines.CoroutineScope
    3. import kotlinx.coroutines.Dispatchers
    4. import kotlinx.coroutines.cancel
    5. import kotlinx.coroutines.delay
    6. import kotlinx.coroutines.launch
    7. fun main() {
    8. //推荐使用这个 不是全局的
    9. val coroutineScope1 = CoroutineScope(Dispatchers.Default)
    10. coroutineScope1.launch {
    11. delay(3000)
    12. println("结束")
    13. }
    14. coroutineScope1.launch {
    15. delay(3000)
    16. println("结束")
    17. }
    18. coroutineScope1.cancel() //可以手动进行取消,不会涉及到全局 整个程序的生命周期
    19. Thread.sleep(4000)
    20. println("主线程结束")
    21. }

    4.Launch分析

    4.1 第一个参数 context: CoroutineContext

    1. package com.tiger.kotlincoroutine.coroutine
    2. import kotlinx.coroutines.CoroutineDispatcher
    3. import kotlinx.coroutines.CoroutineName
    4. import kotlinx.coroutines.CoroutineScope
    5. import kotlinx.coroutines.CoroutineStart
    6. import kotlinx.coroutines.Dispatchers
    7. import kotlinx.coroutines.InternalCoroutinesApi
    8. import kotlinx.coroutines.Job
    9. import kotlinx.coroutines.launch
    10. import kotlinx.coroutines.newCoroutineContext
    11. import kotlinx.coroutines.runBlocking
    12. import kotlin.coroutines.CoroutineContext
    13. import kotlin.coroutines.EmptyCoroutineContext
    14. @OptIn(ExperimentalStdlibApi::class)
    15. fun main() {
    16. val runBlocking = runBlocking {
    17. val launch = this.launch(Dispatchers.Default) {
    18. println(this.coroutineContext.get(CoroutineDispatcher).toString())//拿到调度器信息
    19. }
    20. println(launch)
    21. launch
    22. }//是同一个对象
    23. println(runBlocking)
    24. }

    1. package com.tiger.kotlincoroutine.coroutine
    2. import kotlinx.coroutines.CoroutineDispatcher
    3. import kotlinx.coroutines.CoroutineName
    4. import kotlinx.coroutines.CoroutineScope
    5. import kotlinx.coroutines.CoroutineStart
    6. import kotlinx.coroutines.Dispatchers
    7. import kotlinx.coroutines.InternalCoroutinesApi
    8. import kotlinx.coroutines.Job
    9. import kotlinx.coroutines.launch
    10. import kotlinx.coroutines.newCoroutineContext
    11. import kotlinx.coroutines.runBlocking
    12. import kotlin.coroutines.CoroutineContext
    13. import kotlin.coroutines.EmptyCoroutineContext
    14. @OptIn(ExperimentalStdlibApi::class)
    15. fun main() {
    16. val runBlocking = runBlocking(Dispatchers.IO) {
    17. val launch = this.launch (Dispatchers.Default){
    18. println(this.coroutineContext.get(CoroutineDispatcher).toString())//拿到调度器信息
    19. }
    20. println(launch)
    21. launch
    22. }//是同一个对象
    23. println(runBlocking)
    24. }

     

    4.2 第二个参数 start:CoroutineStart

     

    1. default 是协程默认的启动方式  由默认协程调度去调度 决定在哪一个线程上面执行
    1. val runBlocking = runBlocking(Dispatchers.IO) {
    2. val launch = this.launch{
    3. println("hello")
    4. delay(1000)
    5. println("end")
    6. }
    7. //异步就会走到下面,end不执行
    8. launch.cancel()
    9. }//是同一个对象

    2. ATOMIC

    1. val runBlocking = runBlocking(Dispatchers.IO) {
    2. val launch = this.launch(start = CoroutineStart.ATOMIC){//ATOMIC是一个立即启动的过程 把执行此协程的优先级调上去
    3. println("hello")
    4. delay(1000)
    5. println("end")
    6. }
    7. //异步就会走到下面,end不执行
    8. launch.cancel()
    9. }//是同一个对象

    3.LAZY 可以自己控制何时启动

    1. val runBlocking = runBlocking(Dispatchers.IO) {
    2. val launch = this.launch(start = CoroutineStart.LAZY){//LAZY 可以自己控制何时启动
    3. println("hello")
    4. delay(1000)
    5. println("end")
    6. }
    7. println("先打印,在启动")
    8. //异步就会走到下面,end不执行
    9. launch.start()
    10. }//是同一个对象

    5. async详解

    1. this.async(Dispatchers.Default, start = CoroutineStart.DEFAULT){
    2. println("进来异步了")
    3. delay(1000)
    4. println("被卡住了")
    5. }

    1.获取值方法1

    1. package com.tiger.kotlincoroutine.coroutine
    2. import kotlinx.coroutines.CoroutineScope
    3. import kotlinx.coroutines.CoroutineStart
    4. import kotlinx.coroutines.Dispatchers
    5. import kotlinx.coroutines.async
    6. import kotlinx.coroutines.delay
    7. fun main() {
    8. val coroutineScope = CoroutineScope(Dispatchers.Default)
    9. val async = coroutineScope.async(Dispatchers.Default, start = CoroutineStart.DEFAULT) {
    10. println("进来异步了")
    11. delay(1000)
    12. println("被卡住了")
    13. "协程异步返回值"
    14. }
    15. Thread.sleep(3000)
    16. val completed = async.getCompleted()
    17. println(completed)
    18. }
    1. package com.tiger.kotlincoroutine.coroutine
    2. import kotlinx.coroutines.CoroutineScope
    3. import kotlinx.coroutines.CoroutineStart
    4. import kotlinx.coroutines.Dispatchers
    5. import kotlinx.coroutines.async
    6. import kotlinx.coroutines.delay
    7. import kotlinx.coroutines.runBlocking
    8. fun main() {
    9. runBlocking {
    10. val async = this.async {
    11. test1()
    12. }
    13. for (i in 0..10) {
    14. println("hello $i")
    15. }
    16. val await = async.await()
    17. println(await)
    18. }
    19. }
    20. suspend fun test1():Int{
    21. println("执行中")
    22. delay(3000)
    23. return 100
    24. }

    6.select函数 与 onAwait方法

    1. package com.tiger.kotlincoroutine.coroutine
    2. import kotlinx.coroutines.CoroutineScope
    3. import kotlinx.coroutines.CoroutineStart
    4. import kotlinx.coroutines.Dispatchers
    5. import kotlinx.coroutines.async
    6. import kotlinx.coroutines.delay
    7. import kotlinx.coroutines.runBlocking
    8. import kotlinx.coroutines.selects.select
    9. fun main() {
    10. runBlocking {
    11. val d = this.async {
    12. delay(2000)
    13. test1(1)
    14. }//同时启动的
    15. val c = this.async {
    16. test1(2)
    17. }//同时启动的
    18. //泛型是协程返回的类型
    19. //select可以等待多个协程的结束
    20. //select会阻塞当前的线程
    21. println(select {
    22. c.onAwait.invoke {
    23. "c" //it是协程返回值
    24. }
    25. d.onAwait.invoke {
    26. "d"
    27. }
    28. //谁先执行结束就返回谁
    29. })
    30. println("end")
    31. }
    32. }
    33. suspend fun test1(item:Int):Int{
    34. println("执行中$item")
    35. delay(3000)
    36. return 100
    37. }

    7. withContenxt

    1. package com.tiger.kotlincoroutine.coroutine
    2. import kotlinx.coroutines.CoroutineDispatcher
    3. import kotlinx.coroutines.Dispatchers
    4. import kotlinx.coroutines.delay
    5. import kotlinx.coroutines.runBlocking
    6. import kotlinx.coroutines.withContext
    7. @OptIn(ExperimentalStdlibApi::class)
    8. fun main() {
    9. runBlocking(Dispatchers.IO) {
    10. println(coroutineContext.get(CoroutineDispatcher).toString())
    11. val withContext = withContext(Dispatchers.Default) {
    12. //会对协程有一个阻塞 挂起就是阻塞的意思
    13. delay(2000)
    14. println(coroutineContext.get(CoroutineDispatcher).toString())
    15. //返回值就是lamda最后一行 ,并且结束以后会回到之前的那个协程上面继续执行
    16. "withContext result"
    17. }
    18. println(withContext)
    19. println(coroutineContext.get(CoroutineDispatcher).toString())
    20. }
    21. }

    1. package com.tiger.kotlincoroutine.coroutine
    2. import kotlinx.coroutines.CoroutineDispatcher
    3. import kotlinx.coroutines.Dispatchers
    4. import kotlinx.coroutines.delay
    5. import kotlinx.coroutines.launch
    6. import kotlinx.coroutines.runBlocking
    7. import kotlinx.coroutines.withContext
    8. @OptIn(ExperimentalStdlibApi::class)
    9. fun main() {
    10. //如果不想阻塞当前协程,那就重新开一个
    11. runBlocking(Dispatchers.IO) {
    12. println(coroutineContext.get(CoroutineDispatcher).toString())
    13. launch {
    14. val withContext = withContext(Dispatchers.Default) {
    15. //会对协程有一个阻塞 挂起就是阻塞的意思
    16. delay(2000)
    17. println(coroutineContext.get(CoroutineDispatcher).toString())
    18. //返回值就是lamda最后一行 ,并且结束以后会回到之前的那个协程上面继续执行
    19. "withContext result"
    20. }
    21. println(withContext)
    22. }
    23. println(coroutineContext.get(CoroutineDispatcher).toString())
    24. }
    25. }

    8.suspend关键字

    协程就是任务代码块,有调度器进行线程分配执行此代码块,可以公用一个线程,异步执行代码块,也可以不是一个线程执行.

    suspend 声明一个挂起函数,可以阻塞当前协程去执行代码块里的内容,主要是针对协程的。

    因为 Thread.sleep 是停止线程的,协程是在线程上面跑的。

    delay是延迟当前协程,不停线程,其他协程在此线程上面跑的话,那么都会被停止

  • 相关阅读:
    使用Qt Designer为您的Qt for Python项目创建基于Qt Widgets的图形界面的两种方法
    qt-C++笔记之两个窗口ui的交互
    【论文阅读】TEMPORAL ENSEMBLING FOR SEMI-SUPERVISED LEARNING
    从政府工作报告探云计算、大数据与人工智能的应用与推动作用
    Python每日一练——第9天:选择排序【含动图展示】
    Go使用Gin+mysql实现增删改查
    网上电子元器件采购商城:打破采购环节信息不对称难题,赋能企业高效协同管理
    怎么查找女性人数的不同年龄段的人数
    根据以下电路图,补全STM32F103RCT6的IO口初始化程序
    浅谈keras.preprocessing.text
  • 原文地址:https://blog.csdn.net/qq_53374893/article/details/136231631