介绍:
Kotlin Coroutines 是一种用于简化异步代码的并发设计模式。它基于协程的概念,允许在单个线程上挂起和恢复执行,从而管理长时间运行的任务。协程类似于线程,但不绑定到特定的线程,可以在一个线程中挂起其执行,并在另一个线程中恢复。
Kotlin Coroutines 的特点包括:
- 轻量级:协程可以在单个线程上运行多个协程,因为协程支持挂起,不会使正在运行协程的线程阻塞。挂起比阻塞节省内存,且支持多个并行操作。
- 内存泄漏更少:使用结构化并发机制在一个作用域内执行多项操作。
- 内置取消支持:取消操作会自动在运行中的整个协程层次结构内传播。
- 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