Kotlin中的协程

1、协程是什么

协程是程序中处理并发任务的一种方案,同时也是这种方案的一个组件。

其底层API其实还是基于java线程来实现的。

提示:kotlin已集成了此组件。

相关的包:

package kotlinx.coroutines

2、协程与线程的区别

  • 协程与线程是属于一个层级的,但是却又和线程处理并行任务有着不同的解决方案,协程可以在处理完并发任务之后,自动切回UI(mian/主)线程;

协程的调用案例:

        GlobalScope.launch(Dispatchers.Main) {
            backTask1()
            uiUpdate1()
            backTask2()
            uiUpdate2()
            backTask3()
            uiUpdate3()
        }

输出:

System.out: backTask1==> currentThread :DefaultDispatcher-worker-2
System.out: uiUpdate1==> currentThread :main
System.out: backTask2==> currentThread :DefaultDispatcher-worker-1
System.out: uiUpdate2==> currentThread :main
System.out: backTask3==> currentThread :DefaultDispatcher-worker-2
System.out: uiUpdate3==> currentThread :main
  • 线程处理完并发任务默认是不会直接切回UI(mian/主)线程,需要我们手动去切回UI(mian/主)线程。

例如通过 Handler 通知或者通过 runOnUiThread() 等方式去通知主线程更新UI,这样的话就会多写更多的代码同时操作也会变得复杂,尤其是在反复多次执行耗时任务并更新UI的操作极为明显。

回调地狱似的案例:

	Thread {
            backTask1()
            runOnUiThread {
                uiUpdate1()
                Thread {
                    backTask2()
                    runOnUiThread {
                        uiUpdate2()
                        Thread {
                            backTask3()
                            runOnUiThread {
                                uiUpdate3()
                            }
                        }.start()
                    }
                }.start()
            }
        }.start()

输出:

System.out: backTask1==> currentThread :Thread-573
System.out: uiUpdate1==> currentThread :main
System.out: backTask2==> currentThread :Thread-575
System.out: uiUpdate2==> currentThread :main
System.out: backTask3==> currentThread :Thread-577
System.out: uiUpdate3==> currentThread :main

但我们现在有更简洁的方案,为什么不采用了?

3、如何在Kotlin中使用协程

协程使用的案例:

 override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        GlobalScope.launch(Dispatchers.Main) {
            backTask1()
            uiUpdate1()
            backTask2()
            uiUpdate2()
            backTask3()
            uiUpdate3()
        }
    }
    
 private suspend fun backTask1() {
        withContext(Dispatchers.IO) {
            println("backTask1==> currentThread :" + Thread.currentThread().name)
        }
    }

    private fun uiUpdate1() {
        println("uiUpdate1==> currentThread :" + Thread.currentThread().name)
    }

    private suspend fun backTask2() {
        withContext(Dispatchers.IO) {
            println("backTask2==> currentThread :" + Thread.currentThread().name)
        }
    }

    private  fun uiUpdate2() {
        println("uiUpdate2==> currentThread :" + Thread.currentThread().name)
    }

    private suspend fun backTask3() {
        withContext(Dispatchers.IO) {
            println("backTask3==> currentThread :" + Thread.currentThread().name)
        }
    }

    private fun uiUpdate3() {
        println("uiUpdate3==> currentThread :" + Thread.currentThread().name)
    }

输出:

System.out: backTask1==> currentThread :DefaultDispatcher-worker-2
System.out: uiUpdate1==> currentThread :main
System.out: backTask2==> currentThread :DefaultDispatcher-worker-1
System.out: uiUpdate2==> currentThread :main
System.out: backTask3==> currentThread :DefaultDispatcher-worker-2
System.out: uiUpdate3==> currentThread :main

协程框架 suspend 关键字,主要是用于用于告诉协程去调用,而真正实际的调用协程则是使用 withContext 方法进行协程的切换;

携程最主要的一个好处就是可以实现在IO线程与main线程之间的来回切换。

4、协程使用场景

  • 处理并发任务;

  • 先执行后台任务再更新UI这样反复的操作;

  • 不确定函数执行是否耗时的时候也可。

5、总结

我们可以直接通过协程来进行主线程与协程之间的切换,而且相较于原来传统方式调用的话,可以尽可能的避免回调式地狱,从而可以使我们的写法更加的简洁。

协程还有一个好处,就是他不卡主线程,当我们执行反复的后台任务,然后又要更新UI的任务,这样反复切换的时候并不会造成卡顿,而且代码是串行执行的。

应用场景可用于执行异步和非阻塞任务等。

注意:要进行协程方法的调用,须在协程环境中,类似GlobalScope.launch{}、viewModelScope.launch{}代码块中。




原创不易,求个关注。

在这里插入图片描述

微信公众号: 一粒尘埃的漫旅

里面有很多想对大家说的话,就像和朋友聊聊天。
写代码,做设计,聊生活,聊工作,聊职场。
我见到的世界是什么样子的?
搜索关注我吧。

### 三级标题:Kotlin 协程的概念 Kotlin 协程是一种轻量级的并发编程模型,它允许以同步的方式编写异步代码。协程本质上是用户态的线程,可以在单个线程上高效地运行多个任务。它们通过挂起和恢复机制来实现非阻塞操作,从而避免了传统回调地狱的问题[^2]。 ### 三级标题:Kotlin 协程的基本使用方法 #### 启动协程Kotlin 中,可以使用 `launch` 和 `async` 来启动协程。`launch` 通常用于启动一个不需要返回结果的协程,而 `async` 则用于需要返回结果的情况。两者都可以在特定的作用域内启动协程,例如 `GlobalScope` 或者 `coroutineScope`。 ```kotlin import kotlinx.coroutines.* fun main() = runBlocking { // this: CoroutineScope launch { // 在 GlobalScope 中启动一个新的协程 delay(1000L) println("World!") } println("Hello,") delay(2000L) // 等待直到子协程完成 } ``` #### 挂起函数 挂起函数只能在协程内部调用,或者由其他挂起函数调用。最常用的挂起函数之一是 `delay`,它可以暂停当前协程一段时间而不阻塞线程[^5]。 ```kotlin suspend fun doSomething() { delay(1000) println("Done something") } ``` #### 结构化并发 `coroutineScope` 是 Kotlin 协程中实现结构化并发的核心 API。所有在 `coroutineScope` 内启动的子协程都会与该作用域绑定,并且 `coroutineScope` 会等待所有子协程完成后才返回。此外,任一子协程抛出异常会导致整个作用域取消[^4]。 ```kotlin fun main() = runBlocking { coroutineScope { launch { println("Child coroutine 1 started") delay(500) println("Child coroutine 1 finished") } launch { println("Child coroutine 2 started") delay(300) println("Child coroutine 2 finished") } } println("All child coroutines have completed.") } ``` #### 上下文切换 使用 `withContext` 可以切换协程的执行上下文,比如在 IO 线程中进行一些阻塞性操作[^3]。 ```kotlin fun main() = runBlocking { val result = withContext(Dispatchers.IO) { // 执行耗时操作 "Result from IO" } println(result) } ``` ### 三级标题:简单的协程示例 下面是一个结合了上述概念的简单示例: ```kotlin import kotlinx.coroutines.* fun main() = runBlocking { println("Start of main") // 使用 launch 启动一个协程 val job = launch { println("Start of launched coroutine") delay(1000) println("End of launched coroutine") } // 使用 async 获取结果 val deferred = async { println("Start of async coroutine") delay(500) "Result from async" } // 等待 async 完成并打印结果 println(deferred.await()) // 等待 launch 完成 job.join() println("End of main") } ``` 在这个例子中,我们展示了如何使用 `launch` 和 `async` 来启动协程,并演示了如何使用 `await` 来获取 `async` 的结果以及如何使用 `join` 来等待 `launch` 的完成。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值