关于Kotlin协程-Launch源码分析


我们从最基本的launch用法源码进行分析,带大家走完下面示例的整个流程

这篇文章主要代大家走一遍launch方法的流程

这是根示例,下面说的根示例都是它

GlobalScope.launch {
    print("launch用法")
    delay(1000)
}
复制代码

一、直接进入launch查看源码:

public fun CoroutineScope.launch(
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> Unit
): Job {
    //1-将当前协程作用域的context,与已有的结合起来返回一个新的
    val newContext = newCoroutineContext(context)
    //2-创建一个新的协程
    val coroutine = if (start.isLazy)
        LazyStandaloneCoroutine(newContext, block) else
        StandaloneCoroutine(newContext, active = true)
    //3-执行协程
    coroutine.start(start, coroutine, block)
    return coroutine
}
复制代码

1.1、第一步 先看newCoroutineContext方法

关于一些基础用法不太了解的可以看看这篇文章:juejin.cn/post/695061…

///将当前协程作用域的context,与已有的结合起来返回一个新的
@ExperimentalCoroutinesApi
public actual fun CoroutineScope.newCoroutineContext(context: CoroutineContext): CoroutineContext {
    val combined = coroutineContext + context
    val debug = if (DEBUG) combined + CoroutineId(COROUTINE_ID.incrementAndGet()) else combined
    return if (combined !== Dispatchers.Default && combined[ContinuationInterceptor] == null)
        debug + Dispatchers.Default else debug
}
复制代码

1.2、第二步看if条件语句,因为默认是CoroutineStart.DEFAULT所以,创建的是StandaloneCoroutine

------------------它的传递的泛型是 unit类型,注意后续会用到该泛型

///详细如下--它的主要实现是在AbstractCoroutine中

private open class StandaloneCoroutine(
    parentContext: CoroutineContext,
    active: Boolean
) : AbstractCoroutine<Unit>(parentContext, initParentJob = true, active = active) {
    override fun handleJobException(exception: Throwable): Boolean {
        handleCoroutineException(context, exception)
        return true
    }
}
复制代码

AbstractCoroutine的代码如下,主要看他的继承与抽象接口,后续泛型可用到(比如:CoroutineScope对象等)

public abstract class AbstractCoroutine<in T>(
    parentContext: CoroutineContext,
    initParentJob: Boolean,
    active: Boolean
) : JobSupport(active), Job, Continuation<T>, CoroutineScope {

    ......省略n多代码
}
复制代码

1.3、到了第三步coroutine.start(start, coroutine, block)方法,

参数含义: 1. - start的值为 CoroutineStart.DEFAULT它是协程的一直生效方式 1. - coroutine为上面第二步时创建的协程对象 1. - block的类型是一个CoroutineScope对象的扩展方法,它的返回可以是任意值(个人认为 关键所在,在我们这次分析中它对应,示例中的方法块

二、分析上面的协程开始方法 coroutine.start(start, coroutine, block)

根据指向因为coroutine是StandaloneCoroutine对象它的start方法但是它没有所以是它的父类AbstractCoroutine中的:

public fun <R> start(start: CoroutineStart, receiver: R, block: suspend R.() -> T) {
    ///创建父协程工作
    initParentJob()
    ///开启当前协程任务
    start(block, receiver, this)
}
复制代码

需要注意的是:这里的start方法中的参数,注意观察与下面的不要被名称所误导

2.1、 initParentJob() 方法,///因为在 ·根示例· 中没有父协程,所以返回了

internal fun initParentJobInternal(parent: Job?) {
    assert { parentHandle == null }
    if (parent == null) {///因为在当前示例中没有父协程,所以返回了
        parentHandle = NonDisposableHandle
        return
    }
    parent.start() // make sure the parent is started
    @Suppress("DEPRECATION")
    val handle = parent.attachChild(this)
    parentHandle = handle
    // now check our state _after_ registering (see tryFinalizeSimpleState order of actions)
    if (isCompleted) {
        handle.dispose()
        parentHandle = NonDisposableHandle // release it just in case, to aid GC
    }
}
复制代码

2.2、因为在根示例中没有父协程,所以接下来直接看start(block, receiver, this)方法

2.2.1、start(block, receiver, this)方法这里的start对应第一个参数:start: CoroutineStart,...,它是kotlin的invoke的用法,不清楚 invoke用法的可以搜一下
public fun <R> start(:start: CoroutineStart,... receiver: R, block: suspend R.() -> T) {
    initParentJob()
    start(block, receiver, this)
}
复制代码

参数含义:

block参数变量中的R泛型,在这个根示例中,它代表了CoroutineScope 1. - start的值为 CoroutineStart.DEFAULT它是协程的一直生效方式 1. - receiver是上面的StandaloneCoroutine 1. - this的他指代当前的AbstractCoroutine对象,但是它的具体实现子类为StandaloneCoroutine

2.2.2、所以我们找到CoroutineStart类,查看里面的invoke方法,并且要找到带有三个参数的方法如下:
@InternalCoroutinesApi
public operator fun <R, T> invoke(block: suspend R.() -> T, receiver: R, completion: Continuation<T>): Unit =
    when (this) {
        DEFAULT -> block.startCoroutineCancellable(receiver, completion)
        ATOMIC -> block.startCoroutine(receiver, completion)
        UNDISPATCHED -> block.startCoroutineUndispatched(receiver, completion)
        LAZY -> Unit // will start lazily
    }
复制代码

参数含义: 1. - block为根示例的方法体 1. - receiver是上面的StandaloneCoroutine 1. - completion的他指代当前的AbstractCoroutine对象,他实现了Continuation,但是它的具体实现子类为StandaloneCoroutine

因为:

上面的when表达式,传入当前的CoroutineStart它自身,它是一个enum,它的值是:根据上面1.1示例中的CoroutineScope.launch(...)扩展方法得知它默认是 CoroutineStart.DEFAULT,所以上面代码when走的是 block.startCoroutineCancellable(receiver, completion)方法。

所以: 走的是下面2.2.3这一块代码,,他又是一个协程方法的扩展方法(该方法,可以看出是block的扩展,从根示例 代码 可以知道block就是我们想要执行的方法体)

2.2.3、 增加一个协程取消的监听,R是一个参数变量,在这个根示例中,它代表了CoroutineScope
internal fun <R, T> (suspend (R) -> T).startCoroutineCancellable(
   receiver: R, completion: Continuation<T>,
   onCancellation: ((cause: Throwable) -> Unit)? = null
) =
   runSafely(completion) {
       createCoroutineUnintercepted(receiver, completion).intercepted().resumeCancellableWith(Result.success(Unit), onCancellation)
   }
复制代码

参数含义: 1. - receiver是上面的StandaloneCoroutine 1. - completion 但是它的具体实现子类为StandaloneCoroutine,而他是AbstractCoroutine的子类,它的类型 completion: Continuation,”泛型T“,由继承关系可知是 Unit 类型的

三、 createCoroutineUnintercepted方法,这个根据虚拟机生成不同的实现对象,截图如下

image.png

具体代码如下:T 泛型代表Unit,可以看作一个方法体,该协程的挂起 方法体 扩展了一个名为createCoroutineUnintercepted的方法

@SinceKotlin("1.3")
public actual fun <T> (suspend () -> T).createCoroutineUnintercepted(
    completion: Continuation<T>
): Continuation<Unit> {
    val probeCompletion = probeCoroutineCreated(completion) //1.可以看作一个空的拦截器
    return if (this is BaseContinuationImpl)
        create(probeCompletion)
    else //
        createCoroutineFromSuspendFunction(probeCompletion) {
            (this as Function1<Continuation<T>, Any?>).invoke(it)
        }
}
复制代码

3.1、上面代码其实是StandaloneCoroutine的扩展所以里面的if判断看看--StandaloneCoroutine是否实现过BaseContinuationImpl,结果没有找到该实现,后面查阅资料发现它是通过jvm实现的,在编译时生成的class文件,

我自己验证的话是通过debugg断点调试得出的结果,可以根据当前根示例的kotlin字节码的编译文件查看一些细节: 所以它走的是 create(probeCompletion)代码,它的具体实现,可以查看下面的反编译出的java文件,执行的是他的create方法

GlobalScope.launch {
    print("launch用法")
    delay(1000)
}
复制代码

上面这段代码,转化为Java如下,另取名称“java版根示例”,后面所说java版根示例都是,下面这一段代码:

BuildersKt.launch$default((CoroutineScope)GlobalScope.INSTANCE, (CoroutineContext)null, (CoroutineStart)null, (Function2)(new Function2((Continuation)null) {
   int label;

   @Nullable
   public final Object invokeSuspend(@NotNull Object $result) {
      Object var4 = IntrinsicsKt.getCOROUTINE_SUSPENDED();
      switch(this.label) {
      case 0:
         ResultKt.throwOnFailure($result);
         String var2 = "launch用法";
         boolean var3 = false;
         System.out.print(var2);
         this.label = 1;
         if (DelayKt.delay(1000L, this) == var4) {
            return var4;
         }
         break;
      case 1:
         ResultKt.throwOnFailure($result);
         break;
      default:
         throw new IllegalStateException("call to 'resume' before 'invoke' with coroutine");
      }

      return Unit.INSTANCE;
   }


    ////首先执行到这里,返回一个Continuation类型的Function2,对象
   @NotNull
   public final Continuation create(@Nullable Object value, @NotNull Continuation completion) {
      Intrinsics.checkNotNullParameter(completion, "completion");
      Function2 var3 = new <anonymous constructor>(completion);
      return var3;
   }

   public final Object invoke(Object var1, Object var2) {
      return ((<undefinedtype>)this.create(var1, (Continuation)var2)).invokeSuspend(Unit.INSTANCE);
   }
}), 3, (Object)null);
复制代码

3.2、协程方法体中的那一块内容的方法体是通过jvm实现的,我们可以通过反编译 jadx工具进行查看:

图一: image.png

图二: image.png

由图二可知他就是我们需要执行的东西,反编译出的:他执行的是

fun initKotlin(){
    GlobalScope.launch {
        print("launch用法")
        delay(1000)
    }
}

 public final void initKotlin() {
        BuildersKt__Builders_commonKt.launch$default(GlobalScope.INSTANCE, null, null, new MainActivity$initKotlin$1(null), 3, null);
    }

复制代码

上面出现的位置是:new MainActivity i n i t K o t l i n initKotlin 1(null), 3, null)对应上面字节码转化为的Java相关的Function2的位置,可看下图三

image.png

代码如下
final class MainActivity$initKotlin$1 extends SuspendLambda implements Function2<CoroutineScope, Continuation<? super Unit>, Object> {
    int label;

    MainActivity$initKotlin$1(Continuation<? super MainActivity$initKotlin$1> continuation) {
        super(2, continuation);
    }

    public final Continuation<Unit> create(Object obj, Continuation<?> continuation) {
        return new MainActivity$initKotlin$1<>(continuation);
    }

    public final Object invoke(CoroutineScope coroutineScope, Continuation<? super Unit> continuation) {
        return ((MainActivity$initKotlin$1) create(coroutineScope, continuation)).invokeSuspend(Unit.INSTANCE);
    }

    public final Object invokeSuspend(Object $result) {
        Object coroutine_suspended = IntrinsicsKt.getCOROUTINE_SUSPENDED();
        switch (this.label) {
            case 0:
                ResultKt.throwOnFailure($result);
                System.out.print("launch用法");
                Continuation continuation = this;
                this.label = 1;
                if (DelayKt.delay(1000, continuation) != coroutine_suspended) {
                    break;
                } else {
                    return coroutine_suspended;
                }
            case 1:
                ResultKt.throwOnFailure($result);
                break;
            default:
                throw new IllegalStateException("call to 'resume' before 'invoke' with coroutine");
        }
        return Unit.INSTANCE;
    }
}
复制代码

由上图可知它实现了Function2的接口,所以,可以认为该根示例的作用域:它是实现了SuspendLambda,而SuspendLambda实现了BaseContinuationImpl接口,从这里我们知道了上面第上面的3.1、流程分析步骤没有错

3.3、create(probeCompletion)方法

上面3.1走的create方法,我们可以从上面分析,他走的invoke,最终调用invokeSuspend方法

3.4、 回到 3、步骤中的 createCoroutineUnintercepted 方法中的intercepted()

createCoroutineUnintercepted(receiver, completion).intercepted().resumeCancellableWith(Result.success(Unit), onCancellation)
复制代码

四、 根据流程继续走下去分析我们的SuspendLambda 根示例 中的intercepted()方法

该方法在 ContinuationImpl类中,他的具体实现从上面可知是SuspendLambda类,他们的代码如下:

4.1、、SuspendLambda.class:

internal abstract class SuspendLambda(
    public override val arity: Int,
    completion: Continuation<Any?>? ///StandaloneCoroutine
) : ContinuationImpl(completion), FunctionBase<Any?>, SuspendFunction {
    constructor(arity: Int) : this(arity, null)

    public override fun toString(): String =
        if (completion == null)
            Reflection.renderLambdaToString(this) // this is lambda
        else
            super.toString() // this is continuation
}
复制代码

解释:由create的发起方可知SuspendLambda的参数(completion: Continuation<Any?>)它的值是对应 create(receiver, probeCompletion)方法中的probeCompletion参数,追根溯源发现是StandaloneCoroutine对象。

4.2、、ContinuationImpl类如下:

// State machines for named suspend functions extend from this class
internal abstract class ContinuationImpl(
    completion: Continuation<Any?>?,
    private val _context: CoroutineContext?
) : BaseContinuationImpl(completion) {
    constructor(completion: Continuation<Any?>?) : this(completion, completion?.context)

    public override val context: CoroutineContext
        get() = _context!!


   **///在 三、 示例中3.4中 调用intercepted() 方法,就是这个函数**
    @Transient
    private var intercepted: Continuation<Any?>? = null

    ///默认会从协程上下文中取出 key为ContinuationInterceptor 的值
    在这里取出的值就是上面newCoroutineContext创建的DefaultScheduler对象,它继承了CoroutineDispatcher,此处的      interceptContinuation 就是后者的函数
interceptContinuation 传入的参数是this,这个this就是示例代码中的匿名内部类(SuspendLambda),也就是最终需要分发执行的Continuation


    public fun intercepted(): Continuation<Any?> =
        intercepted
            ?: (context[ContinuationInterceptor]?.interceptContinuation(this) ?: this)
                .also { intercepted = it }

    protected override fun releaseIntercepted() {
        val intercepted = intercepted
        if (intercepted != null && intercepted !== this) {
            context[ContinuationInterceptor]!!.releaseInterceptedContinuation(intercepted)
        }
        this.intercepted = CompletedContinuation // just in case
    }
}
复制代码

解释: 默认会从协程上下文中取出 key为ContinuationInterceptor 的值在这里取出的值就是上面newCoroutineContext创建Dispatchers.Default对象,它是-》DefaultScheduler-》ExperimentalCoroutineDispatcher-》ExecutorCoroutineDispatcher-》CoroutineDispatcher 这样的继承关系,最终他调用的是interceptContinuation方法,他只在基类CoroutineDispatcher中实现了 CoroutineDispatcher对象,代码如下:细节查看下面 第五步骤 示例

public final override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> =
    DispatchedContinuation(this, continuation)
复制代码

1. 所以此处的interceptContinuation 就是后者的函数interceptContinuation 传入的参数是this,这个this就是示例代码中的匿名内部类SuspendLambda,也就是最终需要分发执行的Continuation。

1. 而 (context[ContinuationInterceptor]?.interceptContinuation(this) ?: this)的interceptContinuation方法就是调用的CoroutineDispatcher对象中的

4.3、BaseContinuationImpl类如下:

@SinceKotlin("1.3")
internal abstract class BaseContinuationImpl(
    // This is `public val` so that it is private on JVM and cannot be modified by untrusted code, yet
    // it has a public getter (since even untrusted code is allowed to inspect its call stack).
    public val completion: Continuation<Any?>?
) : Continuation<Any?>, CoroutineStackFrame, Serializable {
    // This implementation is final. This fact is used to unroll resumeWith recursion.
    public final override fun resumeWith(result: Result<Any?>) {
        // This loop unrolls recursion in current.resumeWith(param) to make saner and shorter stack traces on resume
        var current = this
        var param = result
        while (true) {
            // Invoke "resume" debug probe on every resumed continuation, so that a debugging library infrastructure
            // can precisely track what part of suspended callstack was already resumed
            probeCoroutineResumed(current)
            with(current) {
                val completion = completion!! // fail fast when trying to resume continuation without completion
                val outcome: Result<Any?> =
                    try {
                        val outcome = invokeSuspend(param)
                        if (outcome === COROUTINE_SUSPENDED) return
                        Result.success(outcome)
                    } catch (exception: Throwable) {
                        Result.failure(exception)
                    }
                releaseIntercepted() // this state machine instance is terminating
                if (completion is BaseContinuationImpl) {
                    // unrolling recursion via loop
                    current = completion
                    param = outcome
                } else {
                    // top-level completion reached -- invoke and return
                    completion.resumeWith(outcome)
                    return
                }
            }
        }
    }

    protected abstract fun invokeSuspend(result: Result<Any?>): Any?

    protected open fun releaseIntercepted() {
        // does nothing here, overridden in ContinuationImpl
    }

    public open fun create(completion: Continuation<*>): Continuation<Unit> {
        throw UnsupportedOperationException("create(Continuation) has not been overridden")
    }

    public open fun create(value: Any?, completion: Continuation<*>): Continuation<Unit> {
        throw UnsupportedOperationException("create(Any?;Continuation) has not been overridden")
    }

    public override fun toString(): String =
        "Continuation at ${getStackTraceElement() ?: this::class.java.name}"

    // --- CoroutineStackFrame implementation

    public override val callerFrame: CoroutineStackFrame?
        get() = completion as? CoroutineStackFrame

    public override fun getStackTraceElement(): StackTraceElement? =
        getStackTraceElementImpl()
}
复制代码

五、DispatchedContinuation类的实现过程:,找到了他也就完成了下面这段代码的intercepted部分

createCoroutineUnintercepted(receiver, completion).intercepted().resumeCancellableWith(Result.success(Unit), onCancellation)
复制代码

resumeCancellableWith的方法如下:

@InternalCoroutinesApi
public fun <T> Continuation<T>.resumeCancellableWith(
    result: Result<T>,
    onCancellation: ((cause: Throwable) -> Unit)? = null
): Unit = when (this) {
    is DispatchedContinuation -> resumeCancellableWith(result, onCancellation)
    else -> resumeWith(result)
}
复制代码

resumeCancellableWith这段代码走的是is DispatchedContinuation -> resumeCancellableWith(result, onCancellation) 大家可以debugg试试,前面4.2步骤 也给出了分析。

从上面可以后续就是resumeCancellableWith方法了,那就是DispatchedContinuation中的resumeCancellableWith方法

如下:

它继承DispatchedTask ->继承SchedulerTask() ->继承Task ->继承 Runable,可放入线程中去执行。 它继承了Continuation,并使用传进去的参数continuation赋值,所以DispatchedContinuation 也可以当做参数continuation 来使用

注意:这里的参数  @JvmField val continuation: Continuation<T> ,就是对应根示例的方法体

internal class DispatchedContinuation<in T>(
    @JvmField val dispatcher: CoroutineDispatcher,
    @JvmField val continuation: Continuation<T>
) : DispatchedTask<T>(MODE_UNINITIALIZED), CoroutineStackFrame, Continuation<T> by continuation {
   .....省略若干
 
@Suppress("NOTHING_TO_INLINE")
inline fun resumeCancellableWith(
    result: Result<T>,
    noinline onCancellation: ((cause: Throwable) -> Unit)?
) {
    val state = result.toState(onCancellation)
    
    ///dispatcher对应我们的前面 **4.2步骤** 分析得出的Dispatchers.Default+debug的对象
    ///dispatcher.isDispatchNeeded(context)对象就是Dispatchers.Default的isDispatchNeeded方法,他没有实现过重写,所以还是用的基类CoroutineDispatcher中的isDispatchNeeded方法,默认是true
    if (dispatcher.isDispatchNeeded(context)) {
        _state = state
        resumeMode = MODE_CANCELLABLE
        
        ///这里的dispatcher,就是分发器DefaultScheduler对象
        ///在 **4.2步骤** 中分析出了this 对象他就是我们的SuspendLambda对象,也就是我们的根示例
        dispatcher.dispatch(context, this)
    } else {
        executeUnconfined(state, MODE_CANCELLABLE) {
            if (!resumeCancelled(state)) {
                resumeUndispatchedWith(result)
            }
        }
    }
}

}
复制代码

解释:

这里使用分发器,分发任务,你可能会有疑问,为什么不直接去执行,还要去分发后,再去执行呢? 不同的任务,处理的方式不同,例如更新UI的需要在主线程。分发器的功能 是把 任务分给 线程池(默认、IO) 或 Handler(通过handler post 发送任务到主线程)。

在第2步,向 协程上下文CoroutineContext 中 加入了一个默认分发器Dispatchers.Default

5.1、在看DefaultScheduler对象的 dispatcher.dispatch(context, this)过程:也可以说是 根示例 的执行模块

4.2步骤 中分析出了它的继承过程如下,它是-》DefaultScheduler-》 ExperimentalCoroutineDispatcher-》ExecutorCoroutineDispatcher-》CoroutineDispatcher 这样的继承关系,它的dispatcher方法在类 ExperimentalCoroutineDispatcher 中实现 可以看出是通过线程池分发处理

@InternalCoroutinesApi
public open class ExperimentalCoroutineDispatcher(
    private val corePoolSize: Int,
    private val maxPoolSize: Int,
    private val idleWorkerKeepAliveNs: Long,
    private val schedulerName: String = "CoroutineScheduler"
) : ExecutorCoroutineDispatcher() {
    public constructor(
        corePoolSize: Int = CORE_POOL_SIZE,
        maxPoolSize: Int = MAX_POOL_SIZE,
        schedulerName: String = DEFAULT_SCHEDULER_NAME
    ) : this(corePoolSize, maxPoolSize, IDLE_WORKER_KEEP_ALIVE_NS, schedulerName)

    @Deprecated(message = "Binary compatibility for Ktor 1.0-beta", level = DeprecationLevel.HIDDEN)
    public constructor(
        corePoolSize: Int = CORE_POOL_SIZE,
        maxPoolSize: Int = MAX_POOL_SIZE
    ) : this(corePoolSize, maxPoolSize, IDLE_WORKER_KEEP_ALIVE_NS)

    override val executor: Executor
        get() = coroutineScheduler

    // This is variable for test purposes, so that we can reinitialize from clean state
    private var coroutineScheduler = createScheduler()

    override fun dispatch(context: CoroutineContext, block: Runnable): Unit =
        try {
            coroutineScheduler.dispatch(block)
        } catch (e: RejectedExecutionException) {
            // CoroutineScheduler only rejects execution when it is being closed and this behavior is reserved
            // for testing purposes, so we don't have to worry about cancelling the affected Job here.
            DefaultExecutor.dispatch(context, block)
        }
        
    ....
private fun createScheduler() = CoroutineScheduler(corePoolSize, maxPoolSize, idleWorkerKeepAliveNs, schedulerName)


### ....省略若干
复制代码

从上面这段代码可知我们是通过线程池进行挂起函数处理。它是CoroutineScheduler对象的dispatch方法

六、* CoroutineScheduler对象,线程池的分发:

6.1、CoroutineScheduler 是一个协程调度器,使用共享的线程,每个线程就是一个worker。需要执行的协程任务,会被添加到队列中,队列分为worker本地队列和全局队列。worker的本地队列为空的时候,会从其它worker拿来协程任务去执行。

源码分析到这里,后面的流程,应该你也能猜个大概,业务功能,分发器,协程调度类都有了。 这里先从整体上,看一下后续的流程

DispatchedContinuation对象,间接继承了 Runable和直接继承了Continuation类型。所以可得知以下两点

1. 此时业务代码(示例中的匿名内部类 Continuation 类型的),已经被封装成了DispatchedContinuation类型,可通过变量delegate,来获取此Continuation 类型。

1. 因为该对象是Runable类型,所以可在线程中运行协程调度类,主要有这三个工作,1、根据DispatchedContinuation创建任务、2、创建线程,3、执行任务。

1. 在DispatchedContinuation对象的run 函数中,会执行 示例中的匿名内部类 的resumeWith() ->invokeSuspend()。

///6.1、参数block我们的** 根示例 **内容对象

fun dispatch(block: Runnable, taskContext: TaskContext = NonBlockingContext, tailDispatch: Boolean = false) {
    
     ///6.2、
    trackTask() // this is needed for virtual time support
    
    ///6.3、使用DispatchedContinuation 创建任务,最终在线程中执行这个任务
    val task = createTask(block, taskContext)
   
    // try to submit the task to the local queue and act depending on the result
    
    ///6.4、一个worker 就是一个线程,这里尝试把任务加入到worker 的本地队列中
    val currentWorker = currentWorker()
    val notAdded = currentWorker.submitToLocalQueue(task, tailDispatch)
    if (notAdded != null) {
    
     ///6.5、如果本地队列添加失败,就加入到全局队列
        if (!addToGlobalQueue(notAdded)) {
            // Global queue is closed in the last step of close/shutdown -- no more tasks should be accepted
            throw RejectedExecutionException("$schedulerName was terminated")
        }
    }
    val skipUnpark = tailDispatch && currentWorker != null
    // Checking 'task' instead of 'notAdded' is completely okay
    if (task.mode == TASK_NON_BLOCKING) {
    
        if (skipUnpark) return
         ///6.6、在本例中,会执行这句函数,创建线程,执行任务
        signalCpuWork()
    } else {
        // Increment blocking tasks anyway
        signalBlockingWork(skipUnpark = skipUnpark)
    }
}
复制代码

6.2、 signalCpuWork()方法

    //从这个函数的名称,就能看出 是单个work
   fun signalCpuWork() {
        // 尝试获取一个可用的worker,如果获取到了,就直接返回,因为任务已经加入队列中,后面被执行
        if (tryUnpark()) return
        //如果没有获取到,就创建一个新的worker,并start
        if (tryCreateWorker()) return
        tryUnpark()
    }

复制代码

6.3、tryCreateWorker(),看看创建新的worker任务

6.3.1、tryCreateWorker()
private fun tryCreateWorker(state: Long = controlState.value): Boolean {
    val created = createdWorkers(state)
    val blocking = blockingTasks(state)
    val cpuWorkers = (created - blocking).coerceAtLeast(0)
    /*
     * We check how many threads are there to handle non-blocking work,
     * and create one more if we have not enough of them.
     */
    if (cpuWorkers < corePoolSize) {
        val newCpuWorkers = createNewWorker()
        // If we've created the first cpu worker and corePoolSize > 1 then create
        // one more (second) cpu worker, so that stealing between them is operational
        if (newCpuWorkers == 1 && corePoolSize > 1) createNewWorker()
        if (newCpuWorkers > 0) return true
    }
    return false
}
复制代码
6.3.2、createNewWorker():小于核心线程数创建一个新的
private fun createNewWorker(): Int {
    synchronized(workers) {
        // Make sure we're not trying to resurrect terminated scheduler
        if (isTerminated) return -1
        val state = controlState.value
        val created = createdWorkers(state)
        val blocking = blockingTasks(state)
        val cpuWorkers = (created - blocking).coerceAtLeast(0)
        // Double check for overprovision
        if (cpuWorkers >= corePoolSize) return 0
        if (created >= maxPoolSize) return 0
        // start & register new worker, commit index only after successful creation
        val newIndex = createdWorkers + 1
        require(newIndex > 0 && workers[newIndex] == null)
        /*
         * 1) Claim the slot (under a lock) by the newly created worker
         * 2) Make it observable by increment created workers count
         * 3) Only then start the worker, otherwise it may miss its own creation
         */
        val worker = Worker(newIndex)
        workers[newIndex] = worker
        require(newIndex == incrementCreatedWorkers())
        worker.start()
        return cpuWorkers + 1
    }
}
复制代码

上面的关键点在于worker.start()方法,很明显开始执行工作

6.4、internal inner class Worker private constructor() : Thread() {}类的在上面被开启,下面看看它的执行:

internal inner class Worker private constructor() : Thread() {
...
override fun run() = runWorker()


private fun runWorker() {
    var rescanned = false
    while (!isTerminated && state != WorkerState.TERMINATED) {
    
       /// 从队列中 取出第一个任务,参数表示是否从本地队列中查找
        val task = findTask(mayHaveLocalTasks)
        // Task found. Execute and repeat
        if (task != null) {
            rescanned = false
            minDelayUntilStealableTaskNs = 0L
            //重点是这里,执行任务
            executeTask(task)
            continue
        } else {
            mayHaveLocalTasks = false
        }
        /*
         * No tasks were found:
         * 1) Either at least one of the workers has stealable task in its FIFO-buffer with a stealing deadline.
         *    Then its deadline is stored in [minDelayUntilStealableTask]
         *
         * Then just park for that duration (ditto re-scanning).
         * While it could potentially lead to short (up to WORK_STEALING_TIME_RESOLUTION_NS ns) starvations,
         * excess unparks and managing "one unpark per signalling" invariant become unfeasible, instead we are going to resolve
         * it with "spinning via scans" mechanism.
         * NB: this short potential parking does not interfere with `tryUnpark`
         */
        if (minDelayUntilStealableTaskNs != 0L) {
            if (!rescanned) {
                rescanned = true
            } else {
                rescanned = false
                tryReleaseCpu(WorkerState.PARKING)
                interrupted()
                LockSupport.parkNanos(minDelayUntilStealableTaskNs)
                minDelayUntilStealableTaskNs = 0L
            }
            continue
        }
        /*
         * 2) Or no tasks available, time to park and, potentially, shut down the thread.
         * Add itself to the stack of parked workers, re-scans all the queues
         * to avoid missing wake-up (requestCpuWorker) and either starts executing discovered tasks or parks itself awaiting for new tasks.
         */
        tryPark()
    }
    tryReleaseCpu(WorkerState.TERMINATED)
}



private fun executeTask(task: Task) {
    val taskMode = task.mode
    idleReset(taskMode)
    beforeTask(taskMode)
    runSafely(task)
    afterTask(taskMode)
}


///最终执行到了这里
fun runSafely(task: Task) {
    try {
        task.run()
    } catch (e: Throwable) {
        val thread = Thread.currentThread()
        thread.uncaughtExceptionHandler.uncaughtException(thread, e)
    } finally {
        unTrackTask()
    }
}

...

}
复制代码

Worker继承了Thread所以关键在于 override fun run() = runWorker()-》executeTask(task: Task)-》 runSafely(task: Task) 最终执行了 task.run()方法

还记得我们在4.1中它的实现分发器是DispatchedContinuation类,而他的run方法来自于他继承的 DispatchedTask类,所以最终执行DispatchedTask类的run方法

6.5、DispatchedTask的run方法

public final override fun run() {
    assert { resumeMode != MODE_UNINITIALIZED } // should have been set before dispatching
    val taskContext = this.taskContext
    var fatalException: Throwable? = null
    try {
    
       ---------- //1.该参数在DispatchedContinuation 类中被复写,赋值为this,所以这里可以当做DispatchedContinuation类型
        val delegate = delegate as DispatchedContinuation<T>
        
       ------------- //2.在创建DispatchedContinuation 的时候,传入的了两个参数(第8步),其中continuation 就是业务中的匿名内部类
        val continuation = delegate.continuation
        
        withContinuationContext(continuation, delegate.countOrElement) {
            val context = continuation.context
            val state = takeState() // NOTE: Must take state in any case, even if cancelled
            val exception = getExceptionalResult(state)
            /*
             * Check whether continuation was originally resumed with an exception.
             * If so, it dominates cancellation, otherwise the original exception
             * will be silently lost.
             */
            val job = if (exception == null && resumeMode.isCancellableMode) context[Job] else null
            if (job != null && !job.isActive) {
                val cause = job.getCancellationException()
                cancelCompletedResult(state, cause)
                continuation.resumeWithStackTrace(cause)
            } else {
                if (exception != null) {
                    continuation.resumeWithException(exception)
                } else {
                
                    ----------------//3.到这里,continuation 就是业务中的内部类了
                    continuation.resume(getSuccessfulResult(state))
                }
            }
        }
    } catch (e: Throwable) {
        // This instead of runCatching to have nicer stacktrace and debug experience
        fatalException = e
    } finally {
        val result = runCatching { taskContext.afterTask() }
        handleFatalException(fatalException, result.exceptionOrNull())
    }
}
复制代码

上面 continuation.resume(getSuccessfulResult(state)) 这一块点击关系链最终是调用了 ContinuationresumeWith(Result.success(value))方法: 又因为我们上面分析得出根示例的方法体它的结构是:

SuspendLambda-》ContinuationImpl-》BaseContinuationImpl
复制代码

所以最终调用它的resumeWith:如下

public final override fun resumeWith(result: Result<Any?>) {
    // This loop unrolls recursion in current.resumeWith(param) to make saner and shorter stack traces on resume
    var current = this
    var param = result
    while (true) {
        // Invoke "resume" debug probe on every resumed continuation, so that a debugging library infrastructure
        // can precisely track what part of suspended callstack was already resumed
        probeCoroutineResumed(current)
        with(current) {
            val completion = completion!! // fail fast when trying to resume continuation without completion
            val outcome: Result<Any?> =
                try {
                    val outcome = invokeSuspend(param)
                    if (outcome === COROUTINE_SUSPENDED) return
                    Result.success(outcome)
                } catch (exception: Throwable) {
                    Result.failure(exception)
                }
            releaseIntercepted() // this state machine instance is terminating
            if (completion is BaseContinuationImpl) {
                // unrolling recursion via loop
                current = completion
                param = outcome
            } else {
                // top-level completion reached -- invoke and return
                completion.resumeWith(outcome)
                return
            }
        }
    }
}
复制代码

上面的话就是调用 **invokeSuspend(result: Result<Any?>): Any?**流程,到这里整个调用流程就分析完成了

参考: blog.csdn.net/xx326664162… juejin.cn/post/695061… blog.csdn.net/xx326664162…

猜你喜欢

转载自juejin.im/post/7068964511125864462