首页 > 其他分享 >kotlin协程小记

kotlin协程小记

时间:2022-11-02 16:04:44浏览次数:43  
标签:协程 thread Thread Log kotlin name MainActivityXX 小记

例子一:

GlobalScope.launch(Dispatchers.Main) {
    //开启子协程
    withContext(Dispatchers.IO) {
        for (i in 0 until 1000) {
        }
        Log.d("MainActivityXX", "withContext-> thread:" + Thread.currentThread().name)
    }
    Log.d("MainActivityXX", "GlobalScope-> thread:" + Thread.currentThread().name)
}
Log.d("MainActivityXX", "onCreate-> thread:" + Thread.currentThread().name)

打印log:

2022-10-09 20:24:21.100 8371-8371/com.example.xiecheng D/MainActivityXX: onCreate-> thread:main
2022-10-09 20:24:21.131 8371-8412/com.example.xiecheng D/MainActivityXX: withContext-> thread:DefaultDispatcher-worker-1
2022-10-09 20:24:21.258 8371-8371/com.example.xiecheng D/MainActivityXX: GlobalScope-> thread:main

 

例子二:

GlobalScope.launch(Dispatchers.Main) {
    //开启子协程
    withContext(Dispatchers.IO) {
        for (i in 0 until 1000) {
        }
        Log.d("MainActivityXX", "withContext1-> thread:" + Thread.currentThread().name)
        withContext(Dispatchers.IO) {
            for (i in 0 until 1000) {
            }
            Log.d("MainActivityXX", "withContext2-> thread:" + Thread.currentThread().name)
        }
    }
    withContext(Dispatchers.IO) {
        for (i in 0 until 1000) {
        }
        Log.d("MainActivityXX", "withContext3-> thread:" + Thread.currentThread().name)
    }
    Log.d("MainActivityXX", "GlobalScope-> thread:" + Thread.currentThread().name)
}
Log.d("MainActivityXX", "onCreate-> thread:" + Thread.currentThread().name)

打印log:

onCreate-> thread:main
withContext1-> thread:DefaultDispatcher-worker-1
withContext2-> thread:DefaultDispatcher-worker-1
withContext3-> thread:DefaultDispatcher-worker-1
GlobalScope-> thread:main

主线程开启一个协程,并不会阻碍主线程的执行,单个协程内部是串行执行的,这里整一个都是串行执行的是因为withContext是一个挂起函数。

 

GlobalScope.launch(Dispatchers.Main) {
    //开启子协程
    GlobalScope.launch (Dispatchers.IO) {
        Log.d("MainActivityXX", "withContext-> thread:" + Thread.currentThread().name)
    }
    Log.d("MainActivityXX", "GlobalScope-> thread:" + Thread.currentThread().name)
}

打印log:

GlobalScope-> thread:main
withContext-> thread:DefaultDispatcher-worker-1

 

例子二:

GlobalScope.launch(Dispatchers.Main) {
    //开启子协程
    withContext(Dispatchers.IO) {
        get()
        Log.d("MainActivityXX", "withContext-> thread:" + Thread.currentThread().name)
    }
    Log.d("MainActivityXX", "GlobalScope-> thread:" + Thread.currentThread().name)
}
suspend fun get() {
Thread {
Thread.sleep(5000)
Log.d("MainActivityXX", "get-> thread:" + Thread.currentThread().name)
}.start()
}
 

打印log:

2022-11-01 20:56:25.220 20058-20100/com.example.xiecheng D/MainActivityXX: withContext-> thread:DefaultDispatcher-worker-1
2022-11-01 20:56:25.264 20058-20058/com.example.xiecheng D/MainActivityXX: GlobalScope-> thread:main
2022-11-01 20:56:30.222 20058-20103/com.example.xiecheng D/MainActivityXX: get-> thread:Thread-8

协程里面开启线程,那么线程不会受协程影响。

 

例子三:

GlobalScope.launch(Dispatchers.Main) {
    fetchDocs()
}

suspend fun fetchDocs() {                             // Dispatchers.Main
    val result = get("https://developer.android.com") // Dispatchers.IO for `get`
    Log.d("MainActivityXX", "fetchDocs-> thread:" + Thread.currentThread().name) 
}
//withContext本身就是挂起函数
suspend fun get(url: String) = withContext (Dispatchers.IO) {
    Log.d("MainActivityXX", "get-> thread:" + Thread.currentThread().name)
}

打印log:

get-> thread:DefaultDispatcher-worker-1
fetchDocs-> thread:main

使用了挂起函数,会先等待get方法执行完再执行下面得操作。

 

1、挂起函数并不会阻塞其所在线程,这样就极大地提高了线程的并发灵活度,最大化了线程的利用效率。
当在 ThreadA 上运行的 CoroutineA 调用了delay(1000L)函数指定延迟一秒后再运行,ThreadA 会转而去执行 CoroutineB,等到一秒后再来继续执行 CoroutineA

2、withContext本身就是挂起函数。

3、挂起的对象是协程。

4、这个 suspend 关键字,既然它并不是真正实现挂起,它其实是一个提醒。函数的创建者对函数的使用者的提醒:我是一个耗时函数,我被我的创建者用挂起的方式放在后台运行,所以请在协程里调用我。
为什么 suspend 关键字并没有实际去操作挂起,但 Kotlin 却把它提供出来?
因为它本来就不是用来操作挂起的。挂起的操作 —— 也就是切线程,依赖的是挂起函数里面的实际代码,而不是这个关键字。
所以这个关键字,只是一个提醒。
所以,创建一个 suspend 函数,为了让它包含真正挂起的逻辑,要在它内部直接或间接调用 Kotlin 自带的 suspend 函数,你的这个 suspend 才是有意义的。


5、所以这个 suspend,其实并不是起到把任何把协程挂起,或者说切换线程的作用。真正挂起协程这件事,是 Kotlin 的协程框架帮我们做的。
所以我们想要自己写一个挂起函数,仅仅只加上 suspend 关键字是不行的,还需要函数内部直接或间接地调用到 Kotlin 协程框架自带的 suspend 函数才行。

6、开发者需要明白,协程是运行于线程上的,一个线程可以运行多个(可以是几千上万个)协程。线程的调度行为是由 OS 来操纵的,而协程的调度行为是可以由开发者来指定并由编译器来实现的。当协程 A 调用 delay(1000L) 函数来指定延迟1秒后再运行时,协程 A 所在的线程只是会转而去执行协程 B,等到1秒后再把协程 A 加入到可调度队列里。所以说,线程并不会因为协程的延时而阻塞,这样可以极大地提高线程的并发灵活度。

 

标签:协程,thread,Thread,Log,kotlin,name,MainActivityXX,小记
From: https://www.cnblogs.com/tangZH/p/16849169.html

相关文章

  • 【小记】为啥行列式的绝对值等于体积
    其实证明并不是很严谨(我们要证明的是:对于\(n\)个线性无关的\(n\)维向量\(\vec{v_1},\vec{v_2},\cdots,\vec{v_n}\),由它们能围成一个\(n\)维平行多面体\(G=\{\su......
  • 【小记】SG函数
    记号说明:\([2^k]x\)表示数\(x\)在二进制下第\(k\)位(采用这个记号是来自于形式幂级数中记号\([x^k]f(x)\)的启发)。规定游戏如下:给定初始局面,两个人轮流操作,每次使当......
  • 10.30 小记
    感觉咕了好久,晚上补一点。真就重学是吧。[ARC068F]Solitaire首先存在的性质就是队列中一定是先单调递减后单调递增的序列。首先就是取\(k\)次后中间剩下的,可以随便......
  • Kotlin DSL 学习
    之前在《EffectiveKotlin》一书中,有一条专门讲解DSL的:​​考虑为复杂的对象创建定义DSL​​,让我对DSL有了一定的了解。为了能够更熟悉掌握Kotlin上的DSL,用这篇Blog......
  • Kotlin的语法糖太甜啦——开发MC插件遇到的坑
    最近在学习使用Kotlin开发PaperMC插件,遇到了一个大坑,不吐不快。PersistentDataType<T,Z>接口我们可以给物品或方块添加自定义的BNT标签,而这个接口定义的自定义标签的数......
  • 0097-Go-协程
    环境Time2022-08-24Go1.19前言说明参考:https://gobyexample.com/goroutines目标使用Go语言的协程。启动函数协程packagemainimport("fmt""ti......
  • Git常用命令小记
    仓库操作#初始化仓库并将分支命名为[branch]gitinit-b[branch]#将所有文件/文件夹添加到git版本控制(除了.gitignore指定的文件/文件夹)gitadd.#提交并备注信息......
  • Mockito使用方法(Kotlin)
    一、为什么要使用Mockito1.实际案例1.1遇到的问题对于经常维护的项目,经常遇到一个实际问题:需求不停改变,导致架构经常需要修改某些概念的定义。对于某些十分基础又十分......
  • Kotlin Jetpack 实战 | 03. Kotlin 编程的三重境界
    往期文章​​《KotlinJetpack实战:开篇》​​​​《00.写给Java开发者的Kotlin入坑指南》​​​​《01.从一个膜拜大神的Demo开始》​​​​《02.用Kotlin写Gr......
  • Kotlin Jetpack 实战 | 01. 从一个膜拜大神的 Demo 开始
    简介本文属于​​《KotlinJetpack实战》​​系列文章。这是我用Java写的一个“原始架构”的App,名字叫:​​KotlinJetpackInAction​​​,它的功能只有一个:​​膜拜大神!​......