Kotlin : Coroutines 协程—简单应用

介绍:

Kotlin Coroutines 是一种用于简化异步代码的并发设计模式。它基于协程的概念,允许在单个线程上挂起和恢复执行,从而管理长时间运行的任务。协程类似于线程,但不绑定到特定的线程,可以在一个线程中挂起其执行,并在另一个线程中恢复。

Kotlin Coroutines 的特点包括:

  1. 轻量级:协程可以在单个线程上运行多个协程,因为协程支持挂起,不会使正在运行协程的线程阻塞。挂起比阻塞节省内存,且支持多个并行操作。
  2. 内存泄漏更少:使用结构化并发机制在一个作用域内执行多项操作。
  3. 内置取消支持:取消操作会自动在运行中的整个协程层次结构内传播。
  4. Jetpack 集成:许多 Jetpack 库都包含提供全面协程支持的扩展。某些库还提供自己的协程作用域,可供用于结构化并发。

在使用 Kotlin Coroutines 时,开发人员需要了解协程的生命周期,以便正确地控制协程的挂起和恢复。理论上,由于协程不涉及操作系统调度,因此在用户态上进行操作,而线程需要经历用户态与内核态之间的切换,所以协程性能更佳。然而,不同的语言在实现上可能存在差异,例如 Kotlin 协程的底层实现存在线程切换,因此异步任务可能执行在另一条线程上。

总之,Kotlin Coroutines 是一种轻量级、高效的并发编程工具,适用于处理异步任务和长时间运行的操作。通过使用协程,开发人员可以简化代码结构并更好地管理并发执行。

导包

导包网站: https://mvnrepository.com/

Kotlin 复制代码
dependencies {
    ...
    //加入2个
// https://mvnrepository.com/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")

    // https://mvnrepository.com/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-android
    runtimeOnly("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4")


}

1.launch 异步 不阻塞线程

Kotlin 复制代码
package org.example

import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlin.system.measureTimeMillis

/***
 * Coroutines 协程
 * 轻量级线程
 * 生命周期控制
 * 阻塞 非阻塞
 * var
 * val
 * const val
 */
class CoroutinesTest {
    /**
     * CoroutineScope
     * GlobalScope.launch  异步 不阻塞线程
     * 返回 Job 用于控制协程 取消协程...
     * 一个可以用来创建子执行上下文的方法。你可以用它来启动一个新的执行上下文,该上下文可以在异步任务中独立运行,而不会影响应用的其他部分
     * 用途 :用于创建新的执行上下文,这些上下文可以独立运行,用于执行需要独立生命周期的异步任务。
     * 生命周期:创建的执行上下文具有自己的生命周期,你可以在需要时启动和停止它。
     * 并发性:创建的执行上下文也可以并发运行,但它更加灵活,可以用于更细粒度的控制
     * 取消:创建的执行上下文可以通过调用 Isolate.kill() 方法来停止
     * 性能和资源使用:允许创建独立的执行上下文,这可以更好地控制资源和性能,特别是在需要并发处理大量任务时。
     * 隔离性:创建的执行上下文是隔离的,这有助于避免不同任务之间的冲突和相互影响。
     * 错误处理:错误处理方式更加灵活,可以通过捕获异常或使用其他错误处理机制来处理。
     */
    @OptIn(DelicateCoroutinesApi::class)
    fun testLaunch() {
        val time: Long = measureTimeMillis {
            GlobalScope.launch {
                Thread.sleep(1000)
                println("testLaunch 中的  GlobalScope.launch 线程${Thread.currentThread()} hi hellow")
            }

            GlobalScope.launch {
                Thread.sleep(1000)
                println("testLaunch 中的  GlobalScope.launch2 线程${Thread.currentThread()} hi hellow 第二个")
            }
            //停一下等待 上面线程执行完成
            Thread.sleep(2200)
            println("我是最下面的数据")
        }
        println("函数总耗时:$time")
    }
}


fun main() {

    val ff = coroutinesTest();
    ff.testLaunch();
}

运行结果:

Kotlin 复制代码
testLaunch 中的  GlobalScope.launch2 线程Thread[DefaultDispatcher-worker-2,5,main] hi hellow 第二个
testLaunch 中的  GlobalScope.launch 线程Thread[DefaultDispatcher-worker-1,5,main] hi hellow
我是最下面的数据
函数总耗时:2426

2.async异步,不阻塞线程

Kotlin 复制代码
/**
     * CoroutineScope
     * GlobalScope.async 异步 不阻塞线程
     * 返回 Deferred<T> 返回一个 Future 对象,该对象在全局执行上下文中运行。这意味着它将在应用的整个生命周期中运行,不受应用上下文(如生命周期方法)的影响。
     * 用途 :主要用于创建全局的异步任务,这些任务在应用的整个生命周期中运行
     * 生命周期:与应用的生命周期相同,除非你明确地取消了它
     * 并发性:允许你创建全局的异步任务,这些任务可以在应用的整个生命周期中并发运行
     * 取消:Future 对象可以通过调用 Future.cancel() 方法来取消
     * 性能和资源使用:在全局执行上下文中运行,所以可能会影响应用的性能和资源使用。特别是当有大量全局异步任务时,这可能会成为一个问题
     * 隔离性:在全局执行上下文中运行的,因此没有隔离性。这意味着不同的异步任务可以相互影响
     * 错误处理:错误可以通过 Future 的异常处理机制来处理
     */
    fun testAsync() {
        val time: Long = measureTimeMillis {
            GlobalScope.async {
                Thread.sleep(1000)
                println("testLaunch 中的  GlobalScope.async 线程${Thread.currentThread()} hi hellow")
            }
            GlobalScope.async {
                Thread.sleep(1000)
                println("testLaunch 中的  GlobalScope.async2 线程${Thread.currentThread()} hi hellow 第二个")
            }
            //停一下等待 上面线程执行完成
            Thread.sleep(2200)
            println("我是最下面的数据")
        }
        println("函数总耗时:$time")
    }

运行结果:

Kotlin 复制代码
testLaunch 中的  GlobalScope.async 线程Thread[DefaultDispatcher-worker-1,5,main] hi hellow
testLaunch 中的  GlobalScope.async2 线程Thread[DefaultDispatcher-worker-2,5,main] hi hellow 第二个
我是最下面的数据
函数总耗时:2487

3.runBlocking 阻塞线程

Kotlin 复制代码
/**
     *runBlocking ,阻塞线程
     * 顺序执行
     */
    fun testRunBlocking(){
        val time = measureTimeMillis {
            runBlocking {
                println("testRunBlocking 中的  runBlocking 线程${Thread.currentThread()} hi hellow")
                Thread.sleep(2000)
                println("testRunBlocking 中的  runBlocking2 线程${Thread.currentThread()} hi hellow 第二个")
                //延迟 毫秒
                delay(3000)
            }
            println("我是外面的数据")
        }
        println("函数总耗时:$time")
    }

运行结果:

Kotlin 复制代码
testRunBlocking 中的  runBlocking 线程Thread[main,5,main] hi hellow
testRunBlocking 中的  runBlocking2 线程Thread[main,5,main] hi hellow 第二个
我是外面的数据
函数总耗时:5194

4.cancel 和 join

Kotlin 复制代码
 /**
     *runBlocking 会等待内部协程执行完毕才结束
     */
    fun testCancelJoin() = runBlocking {
        val time = measureTimeMillis {
            // launch 异步不阻塞
            val jobL1: Job = launch {
                println("testCancelJoin 中的 jobL1 launch1 线程${Thread.currentThread()} hi hellow")
            }
            // Job
            val jobL2: Job = launch {
                println("testCancelJoin 中的 jobL2 launch2 线程${Thread.currentThread()} hi hellow 第二个")
            }

            //取消jobL2协程执行.
            jobL2.cancel()

            //jobL2,并返回主协程
//            jobL2.cancelAndJoin()

            //Deferred<T>   async 异步不阻塞
            val defA1: Deferred<Unit> = async {
                //repeat 执行指定次数的给定函数操作。
                //当前迭代的从零开始的索引作为参数传递给操作。
                repeat(10) {
                    println("testCancelJoin 中的defA1  async1 线程${Thread.currentThread()} $it hi hellow")
                    delay(200)
                }
            }
            // //取消defA1协程
//            defA1.cancel()

            //取消defA1协程,并返回主协程
//            defA1.cancelAndJoin()

            //需要等待 defA1 协程执行结束 才会执行下面代码
            defA1.join()

            val defA2: Deferred<Unit> = async {
                println("testCancelJoin 中的defA2  async2 线程${Thread.currentThread()} hi hellow")
            }



            println("我是外面的数据 线程${Thread.currentThread()}")
        }
        println("函数总耗时:$time")
}

运行结果:

Kotlin 复制代码
testCancelJoin 中的 jobL1 launch1 线程Thread[main,5,main] hi hellow
testCancelJoin 中的defA1  async1 线程Thread[main,5,main] 0 hi hellow
testCancelJoin 中的defA1  async1 线程Thread[main,5,main] 1 hi hellow
testCancelJoin 中的defA1  async1 线程Thread[main,5,main] 2 hi hellow
testCancelJoin 中的defA1  async1 线程Thread[main,5,main] 3 hi hellow
testCancelJoin 中的defA1  async1 线程Thread[main,5,main] 4 hi hellow
testCancelJoin 中的defA1  async1 线程Thread[main,5,main] 5 hi hellow
testCancelJoin 中的defA1  async1 线程Thread[main,5,main] 6 hi hellow
testCancelJoin 中的defA1  async1 线程Thread[main,5,main] 7 hi hellow
testCancelJoin 中的defA1  async1 线程Thread[main,5,main] 8 hi hellow
testCancelJoin 中的defA1  async1 线程Thread[main,5,main] 9 hi hellow
我是外面的数据 线程Thread[main,5,main]
函数总耗时:2506
testCancelJoin 中的defA2  async2 线程Thread[main,5,main] hi hellow

5.withTimeout

Kotlin 复制代码
    /** runBlocking 阻塞的
     * withTimeout 超时自动取消内部协程
     */
    fun testTimeOut() = runBlocking {
        val time = measureTimeMillis {
            //超时自动取消内部协程 会抛出异常
            withTimeout(3000) {
                //repeat 执行指定次数的给定函数操作。
                //当前迭代的从零开始的索引作为参数传递给操作。
                repeat(200) {
                    println("withTimeout repeat当前迭代的线程 ${Thread.currentThread()} -- $it")
                    delay(300)
                }

                println("withTimeout 的线程 ${Thread.currentThread()} ")
            }

            //超时自动取消内部协程 不会抛出异常
//            withTimeoutOrNull(2000){
//                repeat(200){
//                    println("withTimeoutOrNull repeat当前迭代的线程 ${Thread.currentThread()} -- $it")
//                    delay(300)
//                }
//            }
        }


    }

运行结果:

Kotlin 复制代码
withTimeout repeat当前迭代的线程 Thread[main,5,main] -- 0
withTimeout repeat当前迭代的线程 Thread[main,5,main] -- 1
withTimeout repeat当前迭代的线程 Thread[main,5,main] -- 2
withTimeout repeat当前迭代的线程 Thread[main,5,main] -- 3
withTimeout repeat当前迭代的线程 Thread[main,5,main] -- 4
withTimeout repeat当前迭代的线程 Thread[main,5,main] -- 5
withTimeout repeat当前迭代的线程 Thread[main,5,main] -- 6
withTimeout repeat当前迭代的线程 Thread[main,5,main] -- 7
withTimeout repeat当前迭代的线程 Thread[main,5,main] -- 8
withTimeout repeat当前迭代的线程 Thread[main,5,main] -- 9
Exception in thread "main" kotlinx.coroutines.TimeoutCancellationException: Timed out waiting for 3000 ms
	at kotlinx.coroutines.TimeoutKt.TimeoutCancellationException(Timeout.kt:184)
	at kotlinx.coroutines.TimeoutCoroutine.run(Timeout.kt:154)
	at kotlinx.coroutines.EventLoopImplBase$DelayedRunnableTask.run(EventLoop.common.kt:508)
	at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:284)
	at kotlinx.coroutines.DefaultExecutor.run(DefaultExecutor.kt:108)
	at java.base/java.lang.Thread.run(Thread.java:833)

6.await

Kotlin 复制代码
    /**runBlocking 阻塞的 等待协程执行完毕 这个方法才会结束
     * await() 拿结果
     * getCompleted()   拿结果
     */
    fun testAwait() = runBlocking {
        val time = measureTimeMillis {
            //Deferred<T>   async 异步不阻塞
            val defA1: Deferred<Int> = async {
                println("testAwait 中的defA1  async1 线程${Thread.currentThread()} hi hellow")
                delay(2000)//延迟2秒
                100
            }
//            defA1.join()

            val defA2: Deferred<String> = async {
                println("testAwait 中的defA2  async2 线程${Thread.currentThread()} hi hellow")
//                delay(3000)//延迟3秒
//                "hi hello"
                //调用挂起方法
                getData()
            }
//            defA2.join()
            println("结果:线程${Thread.currentThread()} --- ${defA1.await()}  --${defA2.await()} ")
//            println("结果:线程${Thread.currentThread()} --- ${defA1.getCompleted()}  --${defA2.getCompleted()} ")
        }
        println("函数总耗时:$time")
    }

    // 声明一个 suspend 方法  挂起方法
    suspend fun getData(): String {
        println("testAwait 中的 getData()线程${Thread.currentThread()} hi hellow")
        delay(1000) // 模拟一个长时间运行的操作
        return "Hello, World!"
    }

运行结果:

Kotlin 复制代码
testAwait 中的defA1  async1 线程Thread[main,5,main] hi hellow
testAwait 中的defA2  async2 线程Thread[main,5,main] hi hellow
testAwait 中的 getData()线程Thread[main,5,main] hi hellow
结果:线程Thread[main,5,main] --- 100  --Hello, World! 
函数总耗时:2131
相关推荐
准橙考典22 分钟前
怎么能更好的通过驾考呢?
人工智能·笔记·自动驾驶·汽车·学习方法
密码小丑2 小时前
11月4日(内网横向移动(一))
笔记
鸭鸭梨吖3 小时前
产品经理笔记
笔记·产品经理
萌面小侠Plus3 小时前
Android笔记(三十三):封装设备性能级别判断工具——低端机还是高端机
android·性能优化·kotlin·工具类·低端机
齐 飞3 小时前
MongoDB笔记01-概念与安装
前端·数据库·笔记·后端·mongodb
丫头,冲鸭!!!4 小时前
B树(B-Tree)和B+树(B+ Tree)
笔记·算法
听忆.4 小时前
手机屏幕上进行OCR识别方案
笔记
Selina K5 小时前
shell脚本知识点记录
笔记·shell
5 小时前
开源竞争-数据驱动成长-11/05-大专生的思考
人工智能·笔记·学习·算法·机器学习
霍格沃兹测试开发学社测试人社区6 小时前
软件测试学习笔记丨Flask操作数据库-数据库和表的管理
软件测试·笔记·测试开发·学习·flask