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 中会使用一个共享的线程池来处理这些任务,以便在多个协程之间进行合理的调度。

Kotlin 复制代码
package com.tiger.kotlincoroutine.coroutine

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

fun main() {
    //IO线程  超大密集的计算 Default

    /**
     * IO
     * Default
     * Main
     *
     */
    CoroutineScope(Dispatchers.IO).launch {
        test()
//        withContext(Dispatchers.Main){
//
//        }
    }
    println("主线程")
    Thread.sleep(2000)
}

/**
 * 协程代码块
 */
suspend fun test() {
    println("协程开始")
    delay(1000)
    println("协程结束")
}

1.runBlocking

Kotlin 复制代码
package com.tiger.kotlincoroutine.coroutine

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking

fun main() {
    println("hello")
    //如果给的参数第一个为空,那么它会去找到这个协程外面调用它的这个线程 一般在写Test的时候才用一下 阻塞式协程
    val i = runBlocking (Dispatchers.IO){
        //如果制定了了调度器,它会被分配到另一个线程上面执行 ,但也可以阻塞当前线程
        println(
            Thread.currentThread().name
        )
        //这个协程会阻塞当前线程 同步执行
        delay(2000)
        1
    }
    println(
        Thread.currentThread().name
    )
    println("world $i ")
}
Kotlin 复制代码
package com.tiger.kotlincoroutine.coroutine

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

fun main() {
    println("hello")
    //如果给的参数第一个为空,那么它会去找到这个协程外面调用它调度器 一般在写Test的时候才用一下 阻塞式协程
    //会等里面所有的协程执行完了,才会释放主线程
    val i = runBlocking (Dispatchers.IO){
        //如果制定了了调度器,它会被分配到另一个线程上面执行 ,但也可以阻塞当前线程
        println(
            Thread.currentThread().name
        )

        println(this)
        //this :BlockingCoroutine 可以再次开启一个协程
        val job = this.launch {
            //这个开启的协程不会阻塞当前线程,异步
            println(
                //没有指定 ,他会默认继承上面所在的调度器 被这个调度器管理的线程池的线程去执行
                Thread.currentThread().name
            )
            delay(5200)
        }

        println(job.isActive)
        println(job.cancel())
        println(job.isActive)
        println("延迟了吗")


        //这个协程会阻塞当前线程 同步执行
        delay(2000)
        1
    }
    println(
        Thread.currentThread().name
    )
    println("world $i ")


    /**
     * 总结
     * IO 网络请求 数据库
     * default 密集型数据处理操作 数据计算
     * main UI操作
     *
     */
}
Kotlin 复制代码
package com.tiger.kotlincoroutine.coroutine

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext

fun main() {
    println("hello")
    val i = runBlocking (Dispatchers.IO){

            request{
                //手动切换到UI线程里
                withContext(Dispatchers.Main){
                    //修改UI
                

                }

            }

    }
    println("world $i")
}

suspend fun request(finish:suspend ()->Unit){
    delay(3000)
    println("网络请求成功")
    finish()
}

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

2.GlobalScope

Kotlin 复制代码
package com.tiger.kotlincoroutine.coroutine

import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

fun main() {
    val launch = GlobalScope.launch { //全局指的是整个程序的生命周期 就算Activity销毁了这个GlobalScope还是存在的
        // 这样可能会造成一些奇怪的问题
        delay(3000)
        println("hello")
    }//这不是阻塞当前线程的一个协程操作
    val launch1 = GlobalScope.launch {

    }

    println(launch===launch1)
    //不能调用cancel 方法,因为作用域是整个生命周期的,不能由我们来管理

    while (true);
}

3.CoroutineScope

Kotlin 复制代码
package com.tiger.kotlincoroutine.coroutine

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

fun main() {
    //推荐使用这个  不是全局的
    val coroutineScope1 = CoroutineScope(Dispatchers.Default)


    coroutineScope1.launch {
       delay(3000)

        println("结束")
    }
    coroutineScope1.launch {
        delay(3000)

        println("结束")
    }
    coroutineScope1.cancel() //可以手动进行取消,不会涉及到全局 整个程序的生命周期
    Thread.sleep(4000)
    println("主线程结束")
}

4.Launch分析

4.1 第一个参数 context: CoroutineContext

Kotlin 复制代码
package com.tiger.kotlincoroutine.coroutine

import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineName
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.InternalCoroutinesApi
import kotlinx.coroutines.Job

import kotlinx.coroutines.launch
import kotlinx.coroutines.newCoroutineContext
import kotlinx.coroutines.runBlocking
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext

@OptIn(ExperimentalStdlibApi::class)
fun main() {


    val runBlocking = runBlocking {
        val launch = this.launch(Dispatchers.Default) {
            println(this.coroutineContext.get(CoroutineDispatcher).toString())//拿到调度器信息

        }
        println(launch)
        launch
    }//是同一个对象
    println(runBlocking)

}
Kotlin 复制代码
package com.tiger.kotlincoroutine.coroutine

import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineName
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.InternalCoroutinesApi
import kotlinx.coroutines.Job

import kotlinx.coroutines.launch
import kotlinx.coroutines.newCoroutineContext
import kotlinx.coroutines.runBlocking
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext

@OptIn(ExperimentalStdlibApi::class)
fun main() {


    val runBlocking = runBlocking(Dispatchers.IO) {
        val launch = this.launch (Dispatchers.Default){
            println(this.coroutineContext.get(CoroutineDispatcher).toString())//拿到调度器信息

        }
        println(launch)
        launch
    }//是同一个对象
    println(runBlocking)

}

4.2 第二个参数 start:CoroutineStart

  1. default 是协程默认的启动方式 由默认协程调度去调度 决定在哪一个线程上面执行
Kotlin 复制代码
    val runBlocking = runBlocking(Dispatchers.IO) {
        val launch = this.launch{
            println("hello")
            delay(1000)
            println("end")
        }
        //异步就会走到下面,end不执行
        launch.cancel()
    }//是同一个对象
  1. ATOMIC
Kotlin 复制代码
    val runBlocking = runBlocking(Dispatchers.IO) {
        val launch = this.launch(start = CoroutineStart.ATOMIC){//ATOMIC是一个立即启动的过程 把执行此协程的优先级调上去
            
            println("hello")
            delay(1000)
            println("end")
        }
        //异步就会走到下面,end不执行
        launch.cancel()
    }//是同一个对象

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

Kotlin 复制代码
 val runBlocking = runBlocking(Dispatchers.IO) {
        val launch = this.launch(start = CoroutineStart.LAZY){//LAZY 可以自己控制何时启动
            println("hello")
            delay(1000)
            println("end")
        }
        println("先打印,在启动")
        //异步就会走到下面,end不执行
        launch.start()
    }//是同一个对象

5. async详解

Kotlin 复制代码
  this.async(Dispatchers.Default, start = CoroutineStart.DEFAULT){

                println("进来异步了")
                delay(1000)
                println("被卡住了")


        }

1.获取值方法1

Kotlin 复制代码
package com.tiger.kotlincoroutine.coroutine

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.delay

fun main() {
    val coroutineScope = CoroutineScope(Dispatchers.Default)

    val async = coroutineScope.async(Dispatchers.Default, start = CoroutineStart.DEFAULT) {

        println("进来异步了")
        delay(1000)
        println("被卡住了")

        "协程异步返回值"
    }
        Thread.sleep(3000)
    val completed = async.getCompleted()
    println(completed)
}
Kotlin 复制代码
package com.tiger.kotlincoroutine.coroutine

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking

fun main() {

    runBlocking {
        val async = this.async {
            test1()
        }
        for (i in 0..10) {
            println("hello $i")
        }
        val await = async.await()

        println(await)



    }

}

suspend fun test1():Int{
    println("执行中")
    delay(3000)
    return 100
}

6.select函数 与 onAwait方法

Kotlin 复制代码
package com.tiger.kotlincoroutine.coroutine

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.selects.select

fun main() {

    runBlocking {
        val d = this.async {
            delay(2000)
            test1(1)
        }//同时启动的
        val c = this.async {
            test1(2)
        }//同时启动的

        //泛型是协程返回的类型
        //select可以等待多个协程的结束
        //select会阻塞当前的线程
        println(select<String> {
            c.onAwait.invoke {
                "c"  //it是协程返回值
            }
            d.onAwait.invoke {
                "d"
            }
            //谁先执行结束就返回谁
        })

        println("end")







    }

}

suspend fun test1(item:Int):Int{
    println("执行中$item")
    delay(3000)
    return 100
}

7. withContenxt

Kotlin 复制代码
package com.tiger.kotlincoroutine.coroutine

import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext

@OptIn(ExperimentalStdlibApi::class)
fun main() {
    runBlocking(Dispatchers.IO) {
        println(coroutineContext.get(CoroutineDispatcher).toString())
        val withContext = withContext(Dispatchers.Default) {
            //会对协程有一个阻塞  挂起就是阻塞的意思
            delay(2000)
            println(coroutineContext.get(CoroutineDispatcher).toString())
            //返回值就是lamda最后一行 ,并且结束以后会回到之前的那个协程上面继续执行
            "withContext result"
        }
        println(withContext)
        println(coroutineContext.get(CoroutineDispatcher).toString())
    }
}
Kotlin 复制代码
package com.tiger.kotlincoroutine.coroutine

import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext

@OptIn(ExperimentalStdlibApi::class)
fun main() {
    //如果不想阻塞当前协程,那就重新开一个
    runBlocking(Dispatchers.IO) {
        println(coroutineContext.get(CoroutineDispatcher).toString())
      launch {
          val withContext = withContext(Dispatchers.Default) {
              //会对协程有一个阻塞  挂起就是阻塞的意思
              delay(2000)
              println(coroutineContext.get(CoroutineDispatcher).toString())
              //返回值就是lamda最后一行 ,并且结束以后会回到之前的那个协程上面继续执行
              "withContext result"
          }
          println(withContext)
      }


        println(coroutineContext.get(CoroutineDispatcher).toString())
    }
}

8.suspend关键字

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

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

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

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

相关推荐
&岁月不待人&几秒前
Kotlin by lazy和lateinit的使用及区别
android·开发语言·kotlin
StayInLove4 分钟前
G1垃圾回收器日志详解
java·开发语言
无尽的大道11 分钟前
Java字符串深度解析:String的实现、常量池与性能优化
java·开发语言·性能优化
爱吃生蚝的于勒15 分钟前
深入学习指针(5)!!!!!!!!!!!!!!!
c语言·开发语言·数据结构·学习·计算机网络·算法
binishuaio24 分钟前
Java 第11天 (git版本控制器基础用法)
java·开发语言·git
zz.YE26 分钟前
【Java SE】StringBuffer
java·开发语言
就是有点傻30 分钟前
WPF中的依赖属性
开发语言·wpf
洋24039 分钟前
C语言常用标准库函数
c语言·开发语言
进击的六角龙40 分钟前
Python中处理Excel的基本概念(如工作簿、工作表等)
开发语言·python·excel
wrx繁星点点41 分钟前
状态模式(State Pattern)详解
java·开发语言·ui·设计模式·状态模式