协程(Coroutine-轻量级线程)的使用

mac2024-11-22  27

一般我们需要异步操作的时候,都是通过多线程来实现的,但是线程的创建和开启是个耗性能的操作,开少量的线程没有问题,可是线程多了就有问题了,而且线程还会有各种数据同步的问题。 协程作为一个轻量级的线程,可以完美解决这些问题。你试下开100万个线程?不死机我吃电脑。但是你开100万个协程,那是分分钟的事。 这里只说android和kotlin中的使用。

添加依赖

// kotlin 版本 ext.kotlin_version = '1.3.41' // repository jcenter() // 依赖 implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.0-RC2'

GlobalScope.launch

fun main() { GlobalScope.launch { println("我是一个协程") delay(1000) println("我不会打印,因为主线程已经退出了") } // 和上面的代码并行执行 Thread.sleep(500) println("主线程退出了") }

输出: 我是一个协程 主线程退出了

runBlocking

fun main() { runBlocking { launch { println("协程开始") delay(1000) println("协程结束") } } // 会阻塞等待 runBlocking 中的代码执行完毕 Thread.sleep(500) println("主线程退出了") }

输出: 协程开始 协程结束 主线程退出了

suspend

fun main() { runBlocking { println("开始") launch { test() } println("结束") } } suspend fun test() { delay(1000L) println("我是suspend方法打印的") }

输出: 开始 结束 我是suspend方法打印的

Job

fun main() { runBlocking { println("开始") val job = launch { delay(1000L) println("in launch") } job.join() println("结束") } }

输出: 开始 in launch 结束

cancelAndJoin

Job.cancel 实际上是抛出异常,会直接中断执行。

fun main() { runBlocking { println("开始") val job = launch { try { var i = 1 while (isActive) { print(i++) delay(500L) } } finally { println("\n异常退出") } } delay(1300L) job.cancelAndJoin()// cancel实质上是抛出异常,所以会直接停止,而不会等到delay完后再停止 println("结束") } }

输出: 开始 123 异常退出 结束

withTimeout

Timeout实际上也是抛出异常。

fun main() { runBlocking { println("开始") try { val result = withTimeout(1300) { repeat(10) { print(it) delay(500) } "正常完成,没有Timeout" } println("\n结束 result=$result") } catch (e: TimeoutCancellationException) { println("\n结束 Timeout了") } } }

输出: 开始 012 结束 Timeout了

Channel

Channel相当于BlockingQueue

fun main() { runBlocking { println("开始") val channel = Channel<Int>() launch { for (x in 1..5) channel.send(x * x) channel.close() } for (y in channel) print("$y ") println("\n结束") } }

输出: 开始 1 4 9 16 25 结束

async、await

fun main() { runBlocking { println("开始") val d = async { println("async start...") delay(1000) println("async end") 999 } println("d=${d.await()}") println("结束") } }

如果想要 async 不自行执行,加上 CoroutineStart.LAZY 即可,然后 async 将会等待调用 start 或者 await 后才会执行,如下:

fun main() { runBlocking { println("开始") val d = async(start = CoroutineStart.LAZY) { println("async start...") delay(1000) println("async end") 999 } d.start() println("d=${d.await()}") println("结束") } }

输出: 开始 async start… async end d=999 结束

真正执行线程

fun main() { runBlocking { // 默认执行在当前线程 launch { println("launch\t\t\t\t\t" + Thread.currentThread().name) } // 默认执行在工作线程 GlobalScope.launch { println("GlobalScope.launch\t\t" + Thread.currentThread().name) } // 默认执行在工作线程 launch(Dispatchers.Default) { println("Dispatchers.Default\t\t" + Thread.currentThread().name) } // 默认执行在工作线程 launch(Dispatchers.IO) { println("Dispatchers.IO\t\t\t" + Thread.currentThread().name) } // 不限制的,可能执行在任何线程,甚至里面的不同行代码也会执行在不同的线程 launch(Dispatchers.Unconfined) { println("Dispatchers.Unconfined\t" + Thread.currentThread().name) } // 只有android中才能用main // launch(Dispatchers.Main) { // println("Dispatchers.Main\t\t" + Thread.currentThread().name) // } } }

输出: GlobalScope.launch DefaultDispatcher-worker-1 Dispatchers.Default DefaultDispatcher-worker-3 Dispatchers.IO DefaultDispatcher-worker-3 Dispatchers.Unconfined main launch main

官方文档

https://kotlinlang.org/docs/reference/coroutines/coroutines-guide.html https://github.com/Kotlin/kotlinx.coroutines

最新回复(0)