Kotlin's coroutine principle

Dispatchers.Main
Dispatchers.IO
Dispatchers.Default
Dispatchers.Unconfined

IO and Default use a common thread pool. The difference is that the two have different configurations for the number of core threads and the maximum number of threads.

Default is CPU-intensive, and the number of core threads is equal to the number of CPU cores as much as possible

IO is IO-intensive, the number of core threads is equal to the number of tasks as much as possible, and the maximum number of threads is equal to the maximum of both the number of CPU cores and 64.

The principle is:

Turn on:

When the coroutine is enabled, the compiler will compile the scope (code block) of the coroutine into: SuspendLambda class, which will define a state for the point where the current coroutine is suspended, and each suspension point corresponds to a different state. SuspendLambda This class will save the current execution state. In this way, the code block in the coroutine is divided into many segments, and there is a state point between each segment. Under normal circumstances, the coroutine will execute each piece of code sequentially. And each coroutine corresponds to a Continuation, and this DispatchedContinuation is essentially an instance that implements Runnable. Finally, DispatchedContinuation.resumeWith() will put this DispatchedContinuation into the corresponding thread for execution, IO and Default will be placed in the thread pool, and Main will be executed in the Handler corresponding to the main thread.

hang:

When an API such as withContext() is called in the coroutine, the new coroutine will suspend the current coroutine and call

The suspension in SuspendLambda is abandoned, and the state is changed to: coroutine_suspended. When the state of the coroutine is changed to coroutine_suspended, the execution process will be returned, and the subsequent code will not continue to be executed.

recover:

The child coroutine started that holds a reference to the parent coroutine. When the child coroutine finishes executing, it will call the invokeSuspend() of the parent coroutine's SuspendLambda to change its state to the running state, and the parent coroutine will execute the rest of the code according to the position of the code segment corresponding to the state.

Dispatchers.Unconfined

If the thread is not defined, which coroutine is suspended, it will be executed on the thread of the coroutine.

The principle is that the DispatchedContinuation.resume() method will be called after the coroutine that suspends it is executed. There is a logic in it to determine what the assigned thread is. If it is undefined, it will take out the EventLoop of the thread corresponding to the current coroutine, and pass ThreadLocal to get. Then put the Unconfined task in this EventLoop to execute. This can be done, which thread is suspended, and it will be resumed on the thread corresponding to the coroutine.

Guess you like

Origin blog.csdn.net/Leo_Liang_jie/article/details/122951427