Introduction to Kotlin language foundation: Kotlin collaborative process foundation

Posted by rejoice on Wed, 23 Feb 2022 01:40:08 +0100

1. Blocking and non blocking

**runBlocking**

delay is non blocking, thread Sleep is blocked. Explicitly use the runBlocking coroutine builder to block.

import kotlinx.coroutines.\*



fun main() {

 GlobalScope.launch { // Start a new collaboration in the background and continue

 delay(200)

 "rustfisher.com".forEach {

 print(it)

 delay(280)

 }

 }

 println("The code in the main thread executes immediately")

 runBlocking {     // This expression blocks the main thread

 delay(3000L)  //Blocking the main thread to prevent too fast exit

 }

 println("\n End of example")

}

As you can see, runBlocking uses delay to delay. The main process using runBlocking will remain * * blocked * * until the execution of the internal co process of runBlocking is completed. That is, runBlocking {delay} realizes the blocking effect.

We can also wrap the main function with runBlocking.

import kotlinx.coroutines.\*



fun main() = runBlocking {

 delay(100) // You can use delay here



 GlobalScope.launch {

 delay(100)

 println("Fisher")

 }

 print("Rust ")

 delay(3000)

}

< unit > in runblocking < unit > can be omitted at present.

runBlocking can also be used in testing

// Introduce junit

dependencies {

 implementation("junit:junit:4.13.1")

}

**Unit test**

Set up a Test using @ Test

import org.junit.Test

import kotlinx.coroutines.\*



class C3Test {



 @Test

 fun test1() = runBlocking {

 println("junit Test start ${System.currentTimeMillis()}")

 delay(1234)

 println("junit End of test ${System.currentTimeMillis()}")

 }

}

Operation results

junit Test start 1632401800686

junit End of test 1632401801928

IDEA may prompt no tasks available. You need to change the test option to IDEA, as shown in the following figure.

**Change settings**

2. Wait

Sometimes it is necessary to wait for the execution of the cooperation process. You can use the join() method. This method will suspend the current process until the execution is completed. You need to use main() = runBlocking.

import kotlinx.coroutines.\*



fun main() = runBlocking {

 println("Test wait")

 val job1 = GlobalScope.launch {

 println("job1 start")

 delay(300)

 println("job1 done")

 }

 val job2 = GlobalScope.launch {

 println("job2 start")

 delay(800)

 println("job2 done")

 }



 job2.join()

 job1.join() // wait for

 println("End of test")

}

Run log

Test wait

job1 start

job2 start

job1 done

job2 done

End of test

3. Structured concurrency

Use globalscope When launching, a top-level collaboration will be created. It does not use the main thread. Although the newly created collaborative process is lightweight, it will still consume some memory resources. If you forget to keep the reference to the newly started collaboration, it will continue to run.

We can use structured concurrency in our code.

In the example, we use the runBlocking coroutine builder to convert the main function into a coroutine. There is no need to explicitly use join for the coprocessor started in the scope.

Observe the following example:

import kotlinx.coroutines.\*



fun main() = runBlocking<Unit> {

 println("Main thread id ${Thread.currentThread().id}")

 launch { // Start a new procedure 1 in the runBlocking scope

 println("Thread of coroutine 1 id ${Thread.currentThread().id}")

 delay(300)

 println("Collaboration 1 completed")

 }

 launch { // Start a new process 2 in the runBlocking scope

 println("Thread of coroutine 2 id ${Thread.currentThread().id}")

 delay(500)

 println("Collaboration 2 completed")

 }

 println("Main thread execution completed")

}

Run log

Main thread id 1

Main thread execution completed

Thread of coroutine 1 id 1

Thread of coroutine 2 id 1

Collaboration 1 completed

Collaboration 2 completed

As you can see, you don't need to call thread as before Sleep or delay makes the main thread wait for a period of time to prevent the virtual machine from exiting.

The program will wait until all its co processes are executed, and then really exit.

4. Scope builder

Declare your own scope using the coroutine scope builder. It creates a collaboration scope and waits for all started child collaborations to be executed.

runBlocking looks similar to coroutineScope because they both wait for the body of their coroutines and all their child coroutines to end. The main differences are:

*The runBlocking method blocks the current thread to wait. It is a * * regular function**

*coroutineScope is only suspended, which will release the underlying thread for other purposes. It is a * * suspended function**

The following example shows the features of * * scope builder * *. main is a scope.

import kotlinx.coroutines.\*



fun main() = runBlocking { // this: CoroutineScope

 launch {

 delay(200L)

 println("Synergetic process 1 t${Thread.currentThread().id}")

 }



 coroutineScope { // Create a collaboration scope

 launch {

 delay(500L)

 println("Internal coordination process 2-1 t${Thread.currentThread().id}")

 }



 delay(100L)

 println("Synergetic process 2 t${Thread.currentThread().id}")

 }



 println("Main task completed")

}

Run log

Synergetic process 2 t1

Synergetic process 1 t1

Internal coordination process 2-1t1

Main task completed

5. Extract function reconstruction

Extract the code block inside launch {...} into a separate function. The extracted function needs the * * suspend * * modifier, which is a * * suspended function * *.

import kotlinx.coroutines.delay

import kotlinx.coroutines.launch

import kotlinx.coroutines.runBlocking



fun main() = runBlocking<Unit> {

 launch { r1() }

 println("DONE")

}



// Suspend function

suspend fun r1() {

 delay(300)

 println("Extracted function")

}

log

DONE

Extracted function

6. The coordination process is light

We have also tried to create a lot of collaborative processes before, and the program runs OK.

The following code can output many points

import kotlinx.coroutines.\*



fun main() = runBlocking {

 for (t in 1..10000) {

 launch {

 delay(t \* 500L)

 print(".")

 }

 }

}

7. The global process is like a daemon thread

If only the daemon thread is left in the process, the virtual opportunity exits. In the previous example, you can also see that the program ends before the characters are printed.

The active process started in * * GlobalScope * * does not keep the process alive. They are like daemon threads.

Another example

import kotlinx.coroutines.\*



fun main() = runBlocking {

 GlobalScope.launch {

 for (i in 1..1000000) {

 delay(200)

 println("Collaborative execution: $i")

 }

 }



 delay(1000)

 println("Bye~")

}

log

Collaborative execution: 1

Collaborative execution: 2

Collaborative execution: 3

Collaborative execution: 4

Bye~