Kotlin-协程核心库分析-Job简述

Job是标准库中启动协程后返回的对象,代表着协程本次作业。我们可以判断协程是否结束,是否取消,是否完成并且可以取消当前协程以及嵌套子协程。
一个job 可以理解成他就是一个协程对象。这个job可以开始、取消、状态就监听等操作。

我们简单的看下面的代码如何获取job对象

fun main() {

    val job = GlobalScope.launch {

    }
    //协程是否存活   
    job.isActive
    //是否取消
    job.isCancelled
    //是否完成
    job.isCompleted
    //取消协程
    job.cancel()
    //(非懒启动模式的)启动协程
    job.start()
}

Job继承关系

首先我们注意一点:他继承Element证明他能被放入协程上下文中,且Key为Job。在标准库启动协程后Job对象将放入其上下文中
我们看先一个简单的示例代码:

fun log(msg: String) {
    println("[${Thread.currentThread().name}] ${msg}")
}

fun main() {

    val job = GlobalScope.launch {
        //获取当前的上下文
        val job = coroutineContext
        log("协程内部job:$job")

        val job2=launch {
            val job2=coroutineContext
            log("协程内部job2:$job2")
        }
        log("协程内部job2:$job2")
    }
    
    //协程返回的job和内部或者是同一对象
    log("协程外部的job:$job")
    TimeUnit.HOURS.sleep(1)
}

[main] 协程外部的job:StandaloneCoroutine{Active}@73c6c3b2
[DefaultDispatcher-worker-1] 协程内部job:[StandaloneCoroutine{Active}@73c6c3b2, DefaultDispatcher]
[DefaultDispatcher-worker-1] 协程内部job2:StandaloneCoroutine{Active}@749f0c36
[DefaultDispatcher-worker-2] 协程内部job2:[StandaloneCoroutine{Active}@749f0c36, DefaultDispatcher]

Job 状态

Job有三个暴露的函数用于判断其状态:

  • isActive 当前协程是否存活(创建协程并没有启动协程的时候返回false)
  • isCompleted 当前协程是否完成
  • isCancelle 当前协程是否取消
Demo说明:
fun main() {

    //启动一个懒启动 CoroutineStart.LAZY用说明isActive不一定
    val job = GlobalScope.launch(start = CoroutineStart.LAZY) {
        //获取当前的上下文
        TimeUnit.MILLISECONDS.sleep(500)
        log("协程完成")
    }

    log("未启动协程之前的状态: isActive: [${job.isActive}]  isCompleted: [${job.isCompleted}]  isCancelled: [${job.isCancelled}] ")
    job.start()
    log("启动协程之后的状态: isActive: [${job.isActive}]  isCompleted: [${job.isCompleted}]  isCancelled: [${job.isCancelled}] ")
    TimeUnit.MILLISECONDS.sleep(600)
    log("启动协程完成之后的状态: isActive: [${job.isActive}]  isCompleted: [${job.isCompleted}]  isCancelled: [${job.isCancelled}] ")

    TimeUnit.HOURS.sleep(1)
}

[main] 未启动协程之前的状态: isActive: [false] isCompleted: [false] isCancelled: [false]
[main] 启动协程之后的状态: isActive: [true] isCompleted: [false] isCancelled: [false]
[DefaultDispatcher-worker-1] 协程完成
[main] 启动协程完成之后的状态: isActive: [true] isCompleted: [false] isCancelled: [false]

取消状态Demo:
suspend fun main() {

    //启动一个懒启动 CoroutineStart.LAZY用说明isActive不一定
    val job = GlobalScope.launch(start = CoroutineStart.LAZY) {
        //获取当前的上下文
        TimeUnit.MILLISECONDS.sleep(500)
        log("协程完成")
    }

    log("未启动协程之前的状态: isActive: [${job.isActive}]  isCompleted: [${job.isCompleted}]  isCancelled: [${job.isCancelled}] ")
    job.start()
    log("启动协程之后的状态: isActive: [${job.isActive}]  isCompleted: [${job.isCompleted}]  isCancelled: [${job.isCancelled}] ")
    job.cancel()
    log("启动协程取消之后的状态: isActive: [${job.isActive}]  isCompleted: [${job.isCompleted}]  isCancelled: [${job.isCancelled}] ")
    job.join()
    log("启动协程取消并且之后的状态: isActive: [${job.isActive}]  isCompleted: [${job.isCompleted}]  isCancelled: [${job.isCancelled}] ")

    TimeUnit.HOURS.sleep(1)
}

[main] 未启动协程之前的状态: isActive: [false] isCompleted: [false] isCancelled: [false]
[main] 启动协程之后的状态: isActive: [true] isCompleted: [false] isCancelled: [false]
[main] 启动协程取消之后的状态: isActive: [false] isCompleted: [false] isCancelled: [true]
[DefaultDispatcher-worker-1] 协程完成
[DefaultDispatcher-worker-1] 启动协程取消并且之后的状态: isActive: [false] isCompleted: [true] isCancelled: [true]

当然Job有自己内部的状态变化,然后这些内部的变化比较多,然后部分变化也就对应了我们isActive,isCompleted,isCancelled三个状态的数值。

简要的说明下内部的状态变化:

New 当我们创建一个协程并未启动时候就是出于New状态(使用CoroutineStart.LAZY方式时便可看到).
Active 当我们调用job.start函数的之后,且当前job没有执行完成
Cancelling当我们调用取消的时候立即进入此状态
Cancelled 最终取消任务完成
Completing当协程完成的时候需要等候子协程完成的状态
Completed 协程完成

Job 一些常用方法或者属性

  • isActive 协程是否存活(注意懒启动)
  • isCancelled 协程是否取消
  • isCompleted 协程是否完成
  • cancel() 取消协程
  • start() 启动协程
  • join() 阻塞等候协程完成
  • cancelAndJoin() 取消并等候协程完成
  • invokeOnCompletion( onCancelling: Boolean = false, invokeImmediately: Boolean = true, handler: CompletionHandler)监听协程的状态回调
  • attachChild(child: ChildJob) 附加一个子协程到当前协程上

单独说下 invokeOnCompletion函数:
invokeOnCompletion函数用于监听其完成或者其取消状态,
参数一:onCancelling参数用于判断是否监听取消事件否则监听完成事件,
参数二:invokeImmediately参数主要用于监听已经完成协程时是否回调,如果为false 那么如果在添加监听事件时协程已经完成或取消那么将不会回调.

fun main() = runBlocking{

    val job = GlobalScope.launch {
    }

    job.join()
    job.invokeOnCompletion(onCancelling = false, invokeImmediately = false) {
        log("取消的回调"+it)
    }

    TimeUnit.SECONDS.sleep(10000)
    log("main 结束")
}

上面的例子中:
log("取消的回调"+it)永不执行

你可能感兴趣的:(Kotlin-协程核心库分析-Job简述)