kotlin-协程(什么是一个协程)
1.什么指一个协程对于线程来说一个thread就是就是指一个线程,thread为什么成为线程呢?因为他实现了对线程的一个抽象管理,可以管理这个线程,启动,可以查看各种信息
那么协程呢?
public fun CoroutineScope.launch(context: CoroutineContext = EmptyCoroutineContext,start: CoroutineStart = CoroutineStart.DEFAULT,block: suspend CoroutineScope.() -> Unit
): Job {val newContext = newCoroutineContext(context)val coroutine = if (start.isLazy)LazyStandaloneCoroutine(newContext, block) elseStandaloneCoroutine(newContext, active = true)coroutine.start(start, coroutine, block)return coroutine
}可以看到,启动协程的时候创建了一个StandaloneCoroutine的对象,这个对象是Job的实现类,返回了一个job对象。
job有什么方法呢?
job.start() //启动协程, start: CoroutineStart = CoroutineStart.LAZY // ,的时候得使用job.start方法才会启动协程,才会调用block的代码 job.cancel() //取效协程 job.isActive //判读协程的状态 job.join() //当前的协程阻塞,等待job的协程结束后,再执行当前协程的代码 job.children //子协程的job对象 job.parent //父协程的job对象 job.cancelChildren() //取消所有子协程
那是不是意味着可以把job对象看作一个协程对象呢? 可以也行,但不是全部,job只是管理了协程流程相关的功能,比如开启结束等,但是像协程的名字等是没有的
CoroutineScope是信息最多的,包含可以获取协程的调度器,job等,以及调用launch 和 async去启动一个新的协程,而StandaloneCoroutine也是继承CoroutineScope的
而CoroutineScope里面有一个属性是CoroutineScope,里面全是协程的配置信息
比如:调度器,协程名称,启动模式等
public interface CoroutineScope {public val coroutineContext: CoroutineContext }
协程的父子协程
val parentJob = launch {childJob = launch {delay(200)}}
协程的父子协程是根据job来决定的,在上面的代码中,会把parentJob赋值给childJob的parent属性,会把childJob赋值给parentJob的childJob属性。那怎么相互拿到对方的job呢?
在父协程中启动launch的时候,因为本身就是通过 。CoroutineScope启动的,而CoroutineScope的 coroutineContext 中就可以拿到这个Job。
runBlocking {var childJob:Job?= nullval parentJob = launch(Dispatchers.IO) {childJob = launch {delay(200)}}println("parentJOb${parentJob }")println("childJob=${childJob }")println("childJOb = parentJOb=${childJob?.parent == parentJob }")}
其实看源码可以看到他是复制了父类的coroutineContext的内容
public fun CoroutineScope.launch(context: CoroutineContext = EmptyCoroutineContext,start: CoroutineStart = CoroutineStart.DEFAULT,block: suspend CoroutineScope.() -> Unit
): Job {val newContext = newCoroutineContext(context)val coroutine = if (start.isLazy)LazyStandaloneCoroutine(newContext, block) elseStandaloneCoroutine(newContext, active = true)coroutine.start(start, coroutine, block)return coroutine
}
我们看newCoroutineContextnewCoroutineContext是CoroutineScope的扩展函数,
所以可以拿到当前调用他的launch的CoroutineScope的coroutineContext,和传入的context共同创建一个新的contextpublic actual fun CoroutineScope.newCoroutineContext(context: CoroutineContext): CoroutineContext {val combined = foldCopies(coroutineContext, context, true)val debug = if (DEBUG) combined + CoroutineId(COROUTINE_ID.incrementAndGet()) else combinedreturn if (combined !== Dispatchers.Default && combined[ContinuationInterceptor] == null)debug + Dispatchers.Default else debug
}
kotlin
这里说下我的疑惑点:
第一:parentJob是在 println之前赋值的吗?
打印结果:
parentJObStandaloneCoroutine{Active}@4b553d26
childJob=StandaloneCoroutine{Active}@69a3d1d
childJOb = parentJOb=true
val parentJob = launch(Dispatchers.IO) {childJob = launch {delay(200)}}
这个代码,虽然指定了Dispatchers.IO,但是只是说把block函数扔进了子线程,但是赋值给parentJob是在主线程的,所以在println之前,但是childJob不一定了
public fun CoroutineScope.launch(context: CoroutineContext = EmptyCoroutineContext,start: CoroutineStart = CoroutineStart.DEFAULT,block: suspend CoroutineScope.() -> Unit
): Job {val newContext = newCoroutineContext(context)val coroutine = if (start.isLazy)LazyStandaloneCoroutine(newContext, block) elseStandaloneCoroutine(newContext, active = true)coroutine.start(start, coroutine, block)return coroutine //立即返回对象
}
kotlin的父子协程关系就是通过job来绑定的。
假如,我们把childJob的launch传一个job进去,他们就不是父子协程了,这个时候childJob的父协程是传进去的job,注意传进去的job是父job.
fun main() {runBlocking {CoroutineScope(EmptyCoroutineContext)var childJob:Job?= nullval parentJob = launch(Dispatchers.Default) {childJob = launch(Job()) {delay(200)}delay(300)}println("parentJOb${parentJob }")println("childJob=${childJob }")println("childJOb = parentJOb=${childJob?.parent == parentJob }")}
}
下面的代码打印结果是什么
fun main() {runBlocking {var job1: Job? =nullvar coroutineScope:CoroutineScope? = nullval job = launch {job1= this.coroutineContext[Job]coroutineScope = thisdelay(3000)}delay(100)println("coroutineScope === job1=${coroutineScope === job1 }")println("job === job1=${job === job1 }")}
}
coroutineScope === job1=true
job === job1=true
意思是他们三个其实是一个对象