-
Kotlin files and classes do not have a one-to-one relationship
-
Symbiont
-
inherit
-
Modifier
-
Null pointer problem
text
Key and difficult points
Synergetic process
I've thought about it for a long time. There are a lot of contents on the official website, including basic knowledge, concepts, basic usage, stream operation, channel, exception handling, concurrency processing, etc. It's not convenient to expand here. Specific reference: [Kotlin Chinese website](
)
This chapter only summarizes the knowledge points recently consulted and verified by myself.
concept
English coroutines: /, K ə uru:'ti:n / meaning: collaborative program. It is called collaborative program for short.
Kotlin proposed the concept of coprocessing to simplify asynchronous programming and make it easier for developers to control the execution process of functions.
Relationship and difference between coroutine and thread
In OS, process is the smallest unit of resource allocation, thread is the smallest unit of task scheduling, and coprocess is the * * "micro thread" inside the thread , or lightweight threads * *. Because threads are scarce resources in OS, there is an upper limit on the number of threads on all OS platforms. We usually use thread pool to manage the number of threads in programming. Students familiar with thread pool should know that thread pool management threads, whether core threads or non core threads, will not be created at will unless they have to.
Solving asynchronous problems with threads
- Multithreaded synchronous programming can solve the thread safety problem of data by locking, but locking will reduce the efficiency of program execution, and there will be a potential deadlock if there are too many locks
- The state transition of threads is completely controlled by the kernel, and programmers and developers cannot interfere
- Threads are scarce resources and cannot be created at will. Using threads to solve asynchronous problems, thread initialization, context switching (CPU rotation), thread state switching (sleep, yield...), variable locking operation (synchronized keyword), will make the use of threads more expensive
Solving asynchronous problems with coprocessing
- Coroutines are optimized products running on threads, or "micro threads". Coroutines rely on threads to run, and complex underlying logic is encapsulated in the library. They do not need to care about the thread state when they are used
- Using a collaboration process, developers can control the status of the collaboration process (suspend, resume), rather than relying on the underlying scheduling and time slice contention like threads.
- A thread can run multiple coroutines, and a coroutine can also be executed on multiple threads in segments
- The process is non blocking. After the current process is suspended, the thread resource will not be wasted. It will execute other processes (if any)
- Compared with threads, a scarce resource in OS, coprocesses are extremely lightweight. Even if you open one million coprocesses, the pressure on the system will not be as great as a large number of threads (not to mention one million, the number of threads in linux system is 1000, and beyond this value, the system will not run normally)
- In a word: the emergence of cooperative process has raised the control of program logic by program developers to a new level. Imagine that a function is executing. You want it to pause at one time and continue at another time. I'm afraid it's difficult to use threads. It's easy in cooperative process.
Basic use
module level build.gradle is dependent on import and storage. It is recommended to use the latest version (the current stable version is 1.3.3)
dependencies { //... implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.3" // If you need to use the collaboration scheduler Dispatchers, you must add this dependency }
Creation of collaborative process
There are many ways to create a collaboration, global / independent, synchronous / asynchronous, and the "collaboration scheduler" can be specified
-
runBlocking
fun main() { runBlocking { println("This is runBlocking Synergetic process...") } }
-
launch
fun main() { runBlocking { println("This is runBlocking Synergetic process...") launch { println("This is runBlocking Internal runBlocking Synergetic process...") delay(2000) println("2000 late MS Then print") } } }
-
GlobalScope.launch
fun main() { println("Compared with the main thread, the coroutines are asynchronous, that is, if you insert the coroutine logic here, the logic of the main thread will not be blocked") GlobalScope.launch { delay(3000) println("GlobalScope.launch Create collaboration ") } println("The main thread continues") Thread.sleep(5000) }
-
Global.async
fun main() { runBlocking { val async: Deferred<String> = GlobalScope.async { println("This is an asynchronous coroutine. It will return a Deferred") delay(2000) "Asynchronous task return value" } println("The main thread continues:" + async.await()) } Thread.sleep(5000) }
"Operation"
People who care about collaborative processes are generally very concerned about how convenient it can bring us to asynchronous programming. Here are some operations that are troublesome to implement without collaborative processes.
-
If there is a function, its return value needs to wait until multiple time-consuming asynchronous tasks are executed and returned, and the return values of all tasks are combined as the final return value
fun test6(): String = runBlocking { var finalRes = "" coroutineScope { launch { delay(1000) finalRes = finalRes.plus("1") } launch { delay(2000) finalRes = finalRes.plus("2") } launch { delay(3000) finalRes = finalRes.plus("3") } } finalRes } fun main() { val test6 = test6() println("The final return value is: $test6") }
The final returned result is (print after 3 seconds delay):
The final return value is: 123
-
If there is a function, multiple network requests need to be executed sequentially, and the latter request depends on the execution result of the previous request
import kotlinx.coroutines.* suspend fun getToken(): String { for (i in 0..10) { println("Asynchronous request executing: getToken :$i") delay(100) } return "ask" } suspend fun getResponse(token: String): String { for (i in 0..10) { println("Asynchronous request executing: getResponse :$token $i") delay(100) } return "response" } fun setText(response: String) { println("setText Execution, time: ${System.currentTimeMillis()}") } fun main() { GlobalScope.launch(Dispatchers.Unconfined) { var token = GlobalScope.async(Dispatchers.Unconfined) { return@async getToken() }.await() // An asynchronous task is created, and blocking execution await is the result of blocking execution var response = GlobalScope.async(Dispatchers.Unconfined) { return@async getResponse(token) }.await() // Create an asynchronous task and execute it immediately setText(response) } Thread.sleep(20000) }
Execution results:
Asynchronous request executing: getToken :0 Asynchronous request executing: getToken :1 Asynchronous request executing: getToken :2 Asynchronous request executing: getToken :3 Asynchronous request executing: getToken :4 Asynchronous request executing: getToken :5 Asynchronous request executing: getToken :6 Asynchronous request executing: getToken :7 Asynchronous request executing: getToken :8 Asynchronous request executing: getToken :9 Asynchronous request executing: getToken :10 Asynchronous request executing: getResponse :ask 0 Asynchronous request executing: getResponse :ask 1 Asynchronous request executing: getResponse :ask 2 Asynchronous request executing: getResponse :ask 3 Asynchronous request executing: getResponse :ask 4 Asynchronous request executing: getResponse :ask 5 Asynchronous request executing: getResponse :ask 6 Asynchronous request executing: getResponse :ask 7 Asynchronous request executing: getResponse :ask 8 Asynchronous request executing: getResponse :ask 9 Asynchronous request executing: getResponse :ask 10 setText Execution, time: 1578904290520
-
An asynchronous task is currently being executed, but you suddenly don't want it to be executed. You can cancel it at any time
fun main() { // Collaborative task val job = GlobalScope.launch(Dispatchers.IO) { for (i in 0..100){// Suspend 100MS every time, which is 10 seconds println("The coordination process is being implemented $i") delay(100) } } // But I cancelled the process in one second Thread.sleep(1000) job?.cancel() println( "btn_right End the process") }
Execution results (100 rounds of printing should have been executed, and only 10 rounds lasted):
Collaboration is executing 0 Collaboration in progress 1 The collaboration is being executed 2 The collaboration is in progress 3 The collaboration is being implemented 4 The cooperation process is being implemented 5 The collaboration is being implemented 6 The collaboration is being implemented 7 The collaboration is being implemented 8 The collaboration is being implemented 9 btn_right End the process Process finished with exit code 0
-
If you want a task to be executed for 3 seconds at most, it will be automatically cancelled if it exceeds 3 seconds
import kotlinx.coroutines.* fun main() = runBlocking { println("The results of time limited tasks are:" + getResFromTimeoutTask()) } suspend fun getResFromTimeoutTask(): String? { // Forget, it will ensure that the internal collaboration code is executed, so it can't be written like this return withTimeoutOrNull(1300) {
Automatically cancel after 3 seconds
import kotlinx.coroutines.* fun main() = runBlocking { println("The results of time limited tasks are:" + getResFromTimeoutTask()) } suspend fun getResFromTimeoutTask(): String? { // Forget, it will ensure that the internal collaboration code is executed, so it can't be written like this return withTimeoutOrNull(1300) {