美文网首页JavaKotlin-android
kotlin之协程(五),launch 函数以及协程的取消与超时

kotlin之协程(五),launch 函数以及协程的取消与超时

作者: 不思进取的码农 | 来源:发表于2020-11-05 01:04 被阅读0次

    目录

    kotlin之协程(一),线程,进程,协程,协程可以替换线程吗?
    kotlin之协程(二),Kotlin协程是什么、挂起是什么、挂起的非阻塞式
    kotlin之协程(三),开始创建协程,launch,withContext
    kotlin之协程(四),协程的核心关键字suspend
    kotlin之协程(五),launch 函数以及协程的取消与超时
    kotlin之协程(六),协程中的 async和launch的区别以及runBlocking
    kotlin之协程(七),协程中relay、yield 区别

    如果对于协程需要精细控制,比如说,一个用户也许关闭了一个启动了协程的界面,那么现在协程的执行结果已经不再被需要了,这时,它应该是可以被取消的

    launch 函数

    launch 函数定义

    public fun CoroutineScope.launch(
        context: CoroutineContext = EmptyCoroutineContext,
        start: CoroutineStart = CoroutineStart.DEFAULT,
        block: suspend CoroutineScope.() -> Unit
    ): Job
    
    

    launch 是个扩展函数,接受3个参数,前面2个是常规参数,最后一个是个对象式函数,这样的话 kotlin 就可以使用以前说的闭包的写法:() 里面写常规参数,{} 里面写函数式对象的实现,就像上面的例子一样

    GlobalScope.launch(Dispatchers.Unconfined) {...}
    

    我们需要关心的是 launch 的3个参数和返回值 Job:

    • CoroutineContext - 可以理解为协程的上下文,在这里我们可以设置 CoroutineDispatcher 协程运行的线程调度器,有 4种线程模式:
      • Dispatchers.Default
      • Dispatchers.IO -
      • Dispatchers.Main - 主线程
      • Dispatchers.Unconfined - 没指定,就是在当前线程

    不写的话就是 Dispatchers.Default 模式的,或者我们可以自己创建协程上下文,也就是线程池,newSingleThreadContext 单线程,newFixedThreadPoolContext 线程池

    • CoroutineStart - 启动模式,默认是DEAFAULT,也就是创建就启动;还有一个是LAZY,意思是等你需要它的时候,再调用启动

      • DEAFAULT - 模式模式,不写就是默认
      • ATOMIC -
      • UNDISPATCHED
      • LAZY - 懒加载模式,你需要它的时候,再调用启动
    • block - 闭包方法体,定义协程内需要执行的操作

    • Job - 协程构建函数的返回值,可以把 Job 看成协程对象本身,协程的操作方法都在 Job 身上了

      • job.start() - 启动协程,除了 lazy 模式,协程都不需要手动启动
      • job.join() - 等待协程执行完毕
      • job.cancel() - 取消一个协程
      • job.cancelAndJoin() - 等待协程执行完毕然后再取消

    创建一个协程

    创建该 launch函数返回了一个可以被用来取消运行中的协程的 Job

    val  job = launch {
        repeat(1000) { i ->
            println("job: I'm sleeping $i ...")
            delay(500L)
        }
    }
    

    取消

    val  job = launch {
        repeat(1000) { i ->
            println("job: I'm sleeping $i ...")
            delay(500L)
        }
    }
    delay(1300L) // 延迟一段时间
    println("main: I'm tired of waiting!")
    job.cancel() // 取消该作业
    job.join() // 等待作业执行结束
    println("main: Now I can quit.")
    

    程序执行后的输出如下:

    job: I'm sleeping 0 ...
    job: I'm sleeping 1 ...
    job: I'm sleeping 2 ...
    main: I'm tired of waiting!
    main: Now I can quit.

    一旦 main 函数调用了 job.cancel,我们在其它的协程中就看不到任何输出,因为它被取消了

    超时

    在实践中绝大多数取消一个协程的理由是它有可能超时。 当你手动追踪一个相关 Job的引用并启动了一个单独的协程在延迟后取消追踪,这里已经准备好使用 withTimeout 函数来做这件事。 来看看示例代码:

    withTimeout(1300L) {
        repeat(1000) { i ->
            println("I'm sleeping $i ...")
            delay(500L)
        }
    }
    

    运行后得到如下输出:

    I'm sleeping 0 ...
    I'm sleeping 1 ...
    I'm sleeping 2 ...
    Exception in thread "main" kotlinx.coroutines.TimeoutCancellationException: Timed out waiting for 1300 ms

    这里我们看到了TimeoutCancellationException异常,这异常是因为超时导致的异常取消

    解决这个问题也很简单通过withTimeoutwithTimeoutOrNull函数,代码示例:

    val result = withTimeoutOrNull(1300L) {
        repeat(1000) { i ->
            println("I'm sleeping $i ...")
            delay(500L)
        }
        "Done" // 在它运行得到结果之前取消它
    }
    println("Result is $result")
    

    运行后得到如下输出:

    I'm sleeping 0 ...
    I'm sleeping 1 ...
    I'm sleeping 2 ...
    Result is null

    这样就没有抛出异常了

    (每天学习一点点.每天进步一点点,分享不宜路过点个赞呀,喜欢的点个关注后续更新不断)

    相关文章

      网友评论

        本文标题:kotlin之协程(五),launch 函数以及协程的取消与超时

        本文链接:https://www.haomeiwen.com/subject/tezkvktx.html