Kotlin-协程Coroutines-基本了解

Kotlin中的异步编程:https://kotlinlang.org/docs/async-programming.html#threading

一些处理异步的方案:

  • Threading
  • Callbacks
  • Futures, promises, and others
  • Reactive Extensions
  • Coroutines

协程Coroutines

kotlinx.coroutines 协程库,包含很多丰富的api

使用协程api需要添加依赖,java用java依赖,android用android依赖

dependencies {
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0")
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0")
}

协程是一个可暂停运行的实例,它需要在block代码块中来运行。协程并不绑定到任何特定的线程。
协程可以在一个线程中暂停,在另一个线程中唤醒。
协程可以被认为是轻量级线程,但有很多重要的区别

Your first coroutine

runBlocking launch 都是协程库里的函数

fun main() {

    runBlocking {
         launch {
            delay(1000)
            println("world")
        }
        launch {
            delay(500)
            println("world2222")
        }
        println("hello")
        delay(3000)
    }
    // 先执行上面的协程代码阻塞并执行完毕,最后执行下面这一行
 	println("over")
}

先输出hello,0.5秒后输出world2222,1秒后输出world,最后输出over

launch{} 是一个协程构建者,它启动一个协程block代码块,该block独立运行。

delay() 是一个特殊的暂停or悬挂函数

runBlocking{} 也是一个协程构建者,它运行一个协程并中断阻塞当前线程,直到协程block中的代码运行完。
设计目的就是为了让普通代码具有暂停or悬挂or阻塞功能,可以放到主函数或者测试中使用。真实代码很少使用

Structured concurrency 结构化并发概念:阐述了协程的生命周期及运行范围。
协程的启动及运行只能在特定的协程范围CoroutineScope内。 协程范围外的代码必须要等协程内部block代码运行外才能运行。println(“over”)必须要等待runBlocking{}执行完,才能运行。

Extract function refactoring
可以将协程block中的代码,抽取成一个方法,用suspend修饰符

fun main() = runBlocking { // this: CoroutineScope
    launch { doWorld() }
    println("Hello")
}

// this is your first suspending function
suspend fun doWorld() {
    delay(1000L)
    println("World!")
}

Scope builder coroutineScope{}函数

协程代码块可以通过不同的构建器生成,也可以通过coroutineScope{}来生成。通过 coroutineScope{}来生成的协程,必须要等其及子项的block代码块运行完,才能结束

runBlocking和coroutineScope的构建者可能看起来很相似,
主要区别在于:
runBlocking{}阻塞当前线程,其他资源不能被使用。
coroutineScope{}暂停当前线程,释放底层线程供其他使用,所以其是一个suspend暂停函数

可以在任何suspend暂停函数中使用coroutineScope{}

fun main() = runBlocking {
    doWorld("World!", 2000)
    println("over")

}

suspend fun doWorld(str: String, delayTime: Long) = coroutineScope {
    launch {
        delay(delayTime)
        println(str)
    }
    println("hello")
}

coroutineScope{}可以在suspend暂停函数中执行并发操作
比如开启多个launch{} ,多个协程运行完,coroutineScope{}才结束

suspend fun doWorld() = coroutineScope { // this: CoroutineScope
    launch {
        delay(2000L)
        println("World 2")
    }
    launch {
        delay(1000L)
        println("World 1")
    }
    println("Hello")
}

An explicit job: Job类
launch {} 函数的返回值是Job对象
job.join() 暂停协程,等待job及其子协程完成

public fun CoroutineScope.launch(
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> Unit
): Job{}
val job = launch { // launch a new coroutine and keep a reference to its Job
        delay(1000L)
        println("World!")
    }
    println("Hello")
    job.join() // wait until child coroutine completes
    println("Done")

Job类的方法:
在这里插入图片描述

Coroutines ARE light-weight 协程轻便,占用资源少

试试下面的代码

fun main() = runBlocking {
    repeat(100_000) { // launch a lot of coroutines
        launch {
            delay(5000L)
            print(".")
        }
    }
}

改用原始方式:
去掉runBlocking{} ,launch{}替换为Thread,delay()改为Thread.sleep, 然后再次运行试试

Thread(){
   Thread.sleep(5000)
    print(".")
}.start()

协程的取消

job.cancel() job.join()要配合使用
或者用job.cancelAndJoin()

判断协程状态用属性 isActive 当前协程还在处理中,没有完成也没有被取消

val job = launch {
    repeat(1000) { i ->
        println("job: I'm sleeping $i ...")
        delay(500L)
    }
}
delay(1300L) // delay a bit
println("main: I'm tired of waiting!")
job.cancel() // cancels the job
job.join() // waits for job's completion 

// cancel() join()要配合使用

println("main: Now I can quit.")

不可取消的协程
用withContext(NonCancellable) {}

val job = launch {
    try {
        repeat(1000) { i ->
            println("job: I'm sleeping $i ...")
            delay(500L)
        }
    } finally {
        withContext(NonCancellable) {
            println("job: I'm running finally")
            delay(1000L)
            println("job: And I've just delayed for 1 sec because I'm non-cancellable")
        }
    }
}
delay(1300L) // delay a bit
println("main: I'm tired of waiting!")
job.cancelAndJoin() // cancels the job and waits for its completion
println("main: Now I can quit.")

协程的超时
用withTimeout(){}函数,超时会报异常
withTimeoutOrNull(){}函数,超时返回null

withTimeout(1300L) {
    repeat(1000) { i ->
        println("I'm sleeping $i ...")
        delay(500L)
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值