Kotlin协程核心库分析-2 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[Job]
        log("协程内部job:$job")
    }
	//协程返回的job和内部或者是同一对象
    log("协程外部的job:$job")
    TimeUnit.HOURS.sleep(1)
}

输出:

[main] 协程外部的job:StandaloneCoroutine{Active}@63753b6d
[DefaultDispatcher-worker-1] 协程内部job:StandaloneCoroutine{Active}@63753b6d

Job 状态

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

  1. isActive 当前协程是否存活(创建协程并没有启动协程的时候返回false)
  2. isCompleted 当前协程是否完成
  3. 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(500)
    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] 

由于暴露的相关Api比较简单这里不再过多说明。
当然Job有自己内部的状态变化,然后这些内部的变化比较多,然后部分变化也就对应了我们isActive,isCompleted,isCancelled三个状态的数值。
在这里插入图片描述

在这里插入图片描述

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

Job 一些常用方法或者属性

  1. isActive 协程是否存活(注意懒启动)
  2. isCancelled 协程是否取消
  3. isCompleted 协程是否完成
  4. cancel() 取消协程
  5. start() 启动协程
  6. join() 阻塞等候协程完成
  7. cancelAndJoin() 取消并等候协程完成
  8. invokeOnCompletion( onCancelling: Boolean = false, invokeImmediately: Boolean = true, handler: CompletionHandler) 监听协程的状态回调
  9. 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)永不执行

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值