Kotlin entry-coroutine internal mechanism, kotlin entry coroutine

Source: Internet
Author: User

Kotlin entry-coroutine internal mechanism, kotlin entry coroutine
Suspension Function

?? A new type of function that appears after the coroutine is exposed. A function modified with a special modifier suspend is called a suspension function. A suspended function can only be called in the coroutine and other suspended functions. It cannot be used in other functions. To start a coroutine, it is necessary to suspend the function. for verification, you can view the launch Source Code mentioned in the previous article.

/*** Launch implements the Job interface * @ param context coroutine context. The default value is [DefaultDispatcher]. * @ param start coroutine startup method. The default value is [CoroutineStart. DEFAULT]. * @ param parent indicates the parent Job and overwrites the job through [context. * @ param block the code of the specific coroutine. */public actual fun launch (context: CoroutineContext = DefaultDispatcher, start: CoroutineStart = CoroutineStart. DEFAULT, parent: Job? = Null, block: suspend CoroutineScope. ()-> Unit): Job {...}

?? We can see that the fourth parameter block is a suspension function. When a lambda expression is passed to launch, it is a suspension function. However, this part needs to introduce another coroutine startup function async. Its source code is similar to launch, but async returns a Deferred object, and Deferred inherits from the Job.

public actual fun 
 
   async(    context: CoroutineContext = DefaultDispatcher,    start: CoroutineStart = CoroutineStart.DEFAULT,    parent: Job? = null,    block: suspend CoroutineScope.() -> T): Deferred
  
    {    ...}
  
 

?? Why Deferred-async-await is required for a Job-launch-join? The key to the problem is that Defered inherits from the Job, but it is slightly different:

public actual interface Deferred
 
   : Job {...    public actual suspend fun await(): T}
 

?? From the code above, we can see that the out parameter T (that is, output) is added on the basis of the Deferred inherited Job, And the await function is used to suspend a coroutine and return the final execution result, the join function does not return this item. If the pending function returns a value, you must select async + await to start and suspend the coroutine. The following is an example. The output result is 3:

Fun main (args: Array
 
  
) {RunBlocking
  
   
{Val one = async (coroutineContext) {job1 ()} val two = async (coroutineContext) {job2 ()} println ("Result: $ {one. await () + two. await ()} ") }} suspend fun job1 (): Int {return 1} suspend fun job2 (): Int {return 2}
  
 
Comparison between Job and Deferred

?? Two coroutine startup methods have been learned, but they have various statuses and switching between them. In fact, the authors have listed these in the source code, you only need to copy and paste the following summary.

Job status
Status [IsActive] [IsCompleted] [IsCancelled]
New(Optional initial state) false false false
Active(Default initial state) true false false
Completing(Optional transient state) true false false
Cancelling(Optional transient state) false false true
Cancelled(Final state) false true true
Completed(Final state) false true false
Job status switching process

Several States of Deferred
Status [IsActive] [IsCompleted] [IsCompletedExceptionally] [IsCancelled]
New(Optional initial state) false false false false
Active(Default initial state) true false false false
Completing(Optional transient state) true false false false
Cancelling(Optional transient state) false false false true
Cancelled(Final state) false true true true
Resolved(Final state) false true false false
Failed(Final state) false true true false
Deferred status switching process

Scheduling and thread

?? The coroutine context includes a coroutine scheduler CoroutineDispatcher, which can specify the thread to execute the coroutine. The scheduler can schedule a coroutine to a thread pool and limit it to a specific thread. It can also run without any restrictions. To understand this sentence, you must refer to the first parameter in the launch or async Constructor (See Chapter 1 ).

runBlocking {    val jobs = arrayListOf
 
  ()    jobs += async(Unconfined) {  // 1        println("Unconfined is worked in ${Thread.currentThread()}")    }    jobs += async(coroutineContext) { // 2        println("coroutineContext is worked in ${Thread.currentThread()}")    }    jobs += async(CommonPool) {  // 3        println("CommonPool is worked in ${Thread.currentThread()}")    }    jobs += async(newSingleThreadContext("newThread")) { // 3        println("newThread is worked in ${Thread.currentThread()}")    }    jobs.forEach { it.join() }}
 
NOTE 1: The Unconfined used is an unrestricted context. The coroutine is executed in the stack of the current call until the first suspension. After being suspended, the coroutine can be called by any thread to restart; NOTE 2: coroutineContext inherits CoroutineContext and is executed in the main thread; Comment 3, CommonPool, as mentioned in the previous article, directly inherits CoroutineDispatcher and creates an ExecutorService thread pool internally; Comment 4, create a ThreadPoolDispatcher type that contains the coroutine context of a thread and schedule the coroutine to a fixed thread pool. With the above explanation, the result after the program runs can be guessed as follows:
Internal Mechanism of coroutine

?? The coroutine is fully implemented by the compilation technology (no support from the VM or OS is required) and is suspended for effective by code. Basically, every pending function (optimization may be applicable, but we will not discuss it here) is converted to a state machine, where the State corresponds to the pending call. The next state and related local variables are stored in the fields of the class generated by the compiler just before they are suspended. When the coroutine is restored, the local variable is restored and the state machine starts from the state that just hangs.
?? A suspended coroutine can be stored and transmitted as an object that maintains its pending state and local variables. This type of object is Continuation, and the entire Code Conversion described here corresponds to the classic Continuationpassing style ). Therefore, the suspension function has an additional parameter of the Continuation type as an advanced option.

Summary

?? The usage of coroutine can be summarized first. At present, some APIs of coroutine are still in the experiment, but many new terms have emerged.
-The runBlocking function is mainly used to bridge blocking code (such as Thread) and non-blocking (such as delay) code in the suspension style, so as to ensure the uniformity of the encoding style;
-The launch and async functions both start the coroutine function. async has a return value and returns the Job and Deferred objects respectively;
-The CoroutineDispatcher function is a subclass of CoroutineContext and is used to schedule coroutine.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.