Introduction to the

introduce

This article focuses on the Kotlin composite suspend function. If you have not been exposed to coroutines before, please refer to the article table belowCopy the code

Reference documentation

  1. Google Developers
  2. Kotlin document

Simply combine suspend functions

1. Perform tasks sequentially

The code is as follows:
   private fun test(a) = runBlocking {
        val time = measureTimeMillis {
            val str1 = doIt1()
            val str2 = doIt2()
            Log.d(Constants.TAG, "str1->${str1},str2->${str2}")
        }
        Log.d(Constants.TAG, "Total time:${time}ms")}suspend fun doIt1(a): String {
        delay(1000)
        return "doIt1"
    }

    suspend fun doIt2(a): String {
        delay(1000)
        return "dpIt2"
    }
Copy the code
The log is as follows:
The 2021-09-16 16:42:51. 471, 28858-28858 / demo. Demo. Democoroutines D/Coroutines: Str1 - > doIt1 str2 - > dpIt2 16:42:51. 2021-09-16, 471, 28858-28858 / demo. Demo. Democoroutines D/Coroutines: total time: 2025 msCopy the code
Results analysis:

1. It can be seen that the execution result is 2000+ms, which is the superposition of the sequential execution duration of the two tasks.

2. Asyn performs asynchronous concurrent execution

Code implementation 1 is as follows:
private fun test(a) = runBlocking {
        val time = measureTimeMillis {
            val str1 = async { doIt1() }
            val str2 = doIt2()
            Log.d(Constants.TAG, "str1->${str1.await()},str2->${str2}")
        }
        Log.d(Constants.TAG, "Total time:${time}ms")}suspend fun doIt1(a): String {
        delay(1000)
        return "doIt1"
    }

    suspend fun doIt2(a): String {
        delay(1000)
        return "dpIt2"
    }
Copy the code
Log 1 is as follows:
The 2021-09-16 16:46:42. 394, 29253-29253 / demo. Demo. Democoroutines D/Coroutines: Str1 - > doIt1 str2 - > dpIt2 16:46:42. 2021-09-16, 394, 29253-29253 / demo. Demo. Democoroutines D/Coroutines: total time: 1016 msCopy the code
Code implementation 2 is as follows:
 private fun test(a) = runBlocking {
        val time = measureTimeMillis {
            val str1 = async { doIt1() }
            val str2 = async { doIt2() }
            Log.d(Constants.TAG, "str1+str2->${str1.await()}+${str2.await()}")
        }
        Log.d(Constants.TAG, "Total time:${time}ms")}suspend fun doIt1(a): String {
        delay(1000)
        return "doIt1"
    }

    suspend fun doIt2(a): String {
        delay(1000)
        return "dpIt2"
    }
Copy the code
Log 2 is as follows:
The 2021-09-16 16:53:54. 262, 30702-30702 / demo. Demo. Democoroutines D/Coroutines: Str1 + str2 - > doIt1 + dpIt2 16:53:54. 2021-09-16, 263, 30702-30702 / demo. Demo. Democoroutines D/Coroutines: total time: 1022 msCopy the code
Results analysis:

1. From the time consumption, it can be seen that both tasks are executed in parallel. Method 1 mainly implements doIt1 asynchronously, doIt2 achieves parallelism in normal execution, and method 2 implements both asynchronously. 2, method 2 should not display “await” like method 1, otherwise “await” will result in “await” (+ and, separated, “+” will be executed asynchronously, “separated).

3.Lazy async

The code is as follows:
private fun test(a) = runBlocking {
        val time = measureTimeMillis {
            val str1 = async(start = CoroutineStart.LAZY) { doIt1() }
            val str2 = async(start = CoroutineStart.LAZY) { doIt2() }
            str1.start()
            str2.start()
            Log.d(Constants.TAG, "str1->${str1.await()},str2->${str2.await()}")
        }
        Log.d(Constants.TAG, "Total time:${time}ms")}suspend fun doIt1(a): String {
        delay(1000)
        return "doIt1"
    }

    suspend fun doIt2(a): String {
        delay(1000)
        return "dpIt2"
    }
Copy the code
The log is as follows:
The 2021-09-16 17:08:51. 066, 32123-32123 / demo. Demo. Democoroutines D/Coroutines: Str1 - > doIt1 str2 - > dpIt2 17:08:51. 2021-09-16, 066, 32123-32123 / demo. Demo. Democoroutines D/Coroutines: total time: 1017 msCopy the code
Results analysis:

1. It can be seen from the time consuming that the parallel execution of tasks is also realized.

4. Asyn +coroutineScope structure

Code 1 implements concurrency parallelism:
 private fun test(a) = runBlocking {
        val time = measureTimeMillis {
            Log.d(Constants.TAG, "str->${doIt()}")
        }
        Log.d(Constants.TAG, "Total time:${time}ms")}suspend fun doIt(a): String = coroutineScope {
        val str1 = async { doIt1() }
        val str2 = async { doIt2() }
        str1.await() + str2.await()
    }

    suspend fun doIt1(a): String {
        delay(1000)
        throw RuntimeException("An exception occurred in doIt1")
        return "doIt1"
    }

    suspend fun doIt2(a): String {
        delay(1000)
        return "dpIt2"
    }
Copy the code
Log 1 is as follows:
The 2021-09-16 17:45:01. 940, 3312-3312 / demo. Demo. Democoroutines D/Coroutines: STR - > doIt1dpIt2 17:45:01. 2021-09-16, 941, 3312-3312 / demo. Demo. Democoroutines D/Coroutines: total time: 1022 msCopy the code
Result 1 Analysis:

1. It can be seen from the time consuming that the two tasks are also executed together

Code 2 implements structured concurrency cancellation:

 private fun test(a) = runBlocking {
        val time = measureTimeMillis {
            try {
                val str = doIt()
                Log.d(Constants.TAG, "str->${str}")}catch (e: Exception) {
                Log.d(Constants.TAG,"An exception occurred in doIt:$e")}finally {
                Log.d(Constants.TAG,"doIt-finally")
            }
        }
        Log.d(Constants.TAG, "Total time:${time}ms")}suspend fun doIt(a): String = coroutineScope {
        val str1 = async { doIt1() }
        val str2 = async { doIt2() }
        str1.await() + str2.await()
    }

    suspend fun doIt1(a): String {
        delay(1000)
        throw RuntimeException("DoIt1 - Abnormal execution")}suspend fun doIt2(a): String {
        try {
            delay(2000)}catch (e: Exception) {
            Log.d(Constants.TAG, "doIt2:$e")}finally {
            Log.d(Constants.TAG, "doIt2-finally")}return "dpIt2"
    }
Copy the code
Log 2 is as follows:
The 2021-09-16 17:52:49. 923, 4299-4299 / demo. Demo. Democoroutines D/Coroutines: doIt2:kotlinx.coroutines.JobCancellationException: Parent job is Cancelling; Job = ScopeCoroutine {Cancelling} @ 613 f107 17:52:49 2021-09-16. 923, 4299-4299 / demo. The demo. Democoroutines D/Coroutines: DoIt2 - finally the 2021-09-16 17:52:49. 924, 4299-4299 / demo. The demo. Democoroutines D/Coroutines: DoIt abnormal: Java. Lang. RuntimeException: DoIt1 - perform abnormal 17:52:49 2021-09-16. 924, 4299-4299 / demo. The demo. Democoroutines D/Coroutines: DoIt - finally the 2021-09-16 17:52:49. 924, 4299-4299 / demo. The demo. Democoroutines D/Coroutines: total time: 1028 msCopy the code
Result 2 Analysis:

1. As can be seen from the time consumption, the two tasks are executed in parallel, and the whole doIt task ends after an exception occurs in doIt1. 2, the execution sequence is first after doIt1 exception, doIt2 is cancelled, and then the exception printed by doIt is the exception passed by doIt1.

conclusion

This question mainly introduces the suspension and asynchronous execution of composite functions, as well as the implementation of structured concurrency and its cancellation and exception passing, of course, this is my study notes, I hope to have a little help or inspiration for everyone, I am very happy. Of course, I am also in the process of learning and understanding, recording and understanding inevitably have certain cognitive limitations, if you find any problems, welcome to correct, thanks.Copy the code