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
相关推荐
移动开发者1号4 分钟前
深入理解原子类与CAS无锁编程:原理、实战与优化
android·kotlin
移动开发者1号8 分钟前
深入理解 ThreadLocal:原理、实战与优化指南
android·kotlin
笑衬人心。2 小时前
Ubuntu 22.04 修改默认 Python 版本为 Python3 笔记
笔记·python·ubuntu
金色光环2 小时前
【Modbus学习笔记】stm32实现Modbus
笔记·stm32·学习
zyxzyx6663 小时前
Flyway 介绍以及与 Spring Boot 集成指南
spring boot·笔记
Devil枫3 小时前
Kotlin高级特性深度解析
android·开发语言·kotlin
ChinaDragonDreamer3 小时前
Kotlin:2.1.20 的新特性
android·开发语言·kotlin
西岭千秋雪_4 小时前
Redis性能优化
数据库·redis·笔记·学习·缓存·性能优化
HuashuiMu花水木5 小时前
Matplotlib笔记4----------图像处理
图像处理·笔记·matplotlib
DES 仿真实践家6 小时前
【Day 11-N22】Python类(3)——Python的继承性、多继承、方法重写
开发语言·笔记·python