有限资源分配:coroutines 非同步 suspend async

程序不执行,就只是占据硬碟空间的program

一旦启动,就会产生process;多次启动,就会产生多个process

process可以挪用记忆体和各种系统允许它使用的资源,它所拥有的资源会分配给属下thread;但每个thread同一时间只能负责一个工作,稍微有些沈重,所以後来出现了coroutinescoroutines是个投机者,可以按照开发者的指令,一会儿和这个thread借一下,一会儿在那个thread借一下,自由运用thread,很适合负责可以切割、零碎的工作。

所以coroutines也是Kotlin的必考题之一。

「今天来个小测验,用coroutines写倒数计时器吧。」唯心眼看诗忆马上就要动手开始写,急忙补充说明。「秒数是使用者可以动态输入的唷。」

诗忆首先开启kotlin的coroutines函式库网页,查到了artifact id和最新版本号,加进build.gradle.kts里。

https://github.com/Kotlin/kotlinx.coroutines/blob/master/README.md#using-in-your-projects

implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2")

动态输入意味着main函式参数不再空白,诗忆参考讲义上的范例在main函式放进字串阵列参数。此外,为了验证时间没有错误,她将经过的毫秒数存进timeDelay变数。

import kotlin.system.measureTimeMillis
import kotlinx.coroutines.*

fun main(args : Array<String>) {
    val argTimer = args[0].toInt()
    val timeDelay = measureTimeMillis {
        delay(argTimer * 1000L)
    }
    println("$argTimer seconds pass. Time is up!")
    println("timeDelay: $timeDelay")
}

还没开始执行程序,IDE就已经提醒她delay函式因为有suspend特性,只能放在coroutines或是其他suspend函式。

图1

「学姐,我记得runBlocking可以直接在当下的thread开一个coroutines环境,对吗?」诗忆有点没把握,写之前还是想和唯心确认一下。

「对唷。」唯心给了肯定的答覆。

诗忆很放心的加上runBlocking并加上倒数计时结束印出的字串。

fun main(args : Array<String>) {
    val argTimer = args[0].toInt()
    runBlocking {
        val timeDelay = measureTimeMillis {
            println(delayForMe(argTimer))
        }
        println("timeDelay: $timeDelay")
    }
}
suspend fun delayForMe(seconds :Int): String {
    delay(seconds * 1000L)
    return "$seconds seconds pass. Time is up!"
}

警告消失之後,执行程序还是产生了错误Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0

「学姐,要怎麽在IDE输入参数啊?」

「平常出现执行功能的地方,不要按太快,清单里有一个可以修改Run Configuration的入口,进去後修改Program arguments就可以了。」

图2

图3

诗忆修改成3之後,重新执行程序。

图4

「嗯⋯⋯如果这样写的话,只能一次一个倒数计时,你试试用asyncawait的组合,放进两个delayForMe试试。」唯心建议着。

fun main(args : Array<String>) {
    val argTimer = args[0].toInt()
    runBlocking {
        val timeDelay = measureTimeMillis {
            val one = async {  delayForMe(argTimer) }
            val two = async {  delayForMe(argTimer) }
            println(one.await() + two.await())
        }
        println("timeDelay: $timeDelay")
    }
}  
suspend fun delayForMe(seconds :Int): String {
    delay(seconds * 1000L)
    return "$seconds seconds pass. Time is up!"
}

图5

「喔喔,这样两个倒数计时不会影响到对方!」诗忆惊喜的看着新结果。

「是呀,像现在我另外写一个把每秒钟印出的函式,可以直接加入,不用改到你原本的倒数计时函式。啊,不过文案还是会修改的,要不然看起来会太累赘呢。」

import kotlin.system.measureTimeMillis
import kotlinx.coroutines.*

fun main(args : Array<String>) {
    val argTimer = args[0].toInt()
    runBlocking {
        val timeDelay = measureTimeMillis {
            val one = async {  delayForMe(argTimer) }
            repeat(argTimer) {
                val two = async { delayFor1Sec(it + 1) }
                println(two.await())
            }
            println(one.await())
        }
        println("timeDelay: $timeDelay")
    }
}
suspend fun delayForMe(seconds :Int): String {
    delay(seconds * 1000L)
    return "Time is up!"
}
suspend fun delayFor1Sec(seconds :Int): String {
    delay(1000L)
    return "$seconds seconds pass."
}

图6


<<:  【Day 16】InnoDB indexing

>>:  [经典回顾]硬碟装满资料会变重吗?

Day11 远端共同协作 - 使用 GitHub

大家好我是乌木白,今天来向大家介绍GitHub,我自己很喜欢的一个可以做很多功能的网站!! 什麽是...

【I Love Vue 】 Day 27 爱荷华博弈任务(八) - 测验画面2

我们接着继续开发 测验区 的部分 测验区 先来看看画面: 可以看到测试区除了上面的总分之外,我们有四...

Kneron - 在Raspberry Pi 4(Raspbian Buster)上安装 OpenCV 参考笔记

Kneron - 在Raspberry Pi 4(Raspbian Buster)上安装 OpenC...

30天轻松学会unity自制游戏-新增死亡画面

通常游戏会有一个死亡画面,询问要重新开始,离开,增强能力(看广告)…等,先一样在画布上点右键给一个i...

如何清理Windows 10中的更新缓存

您在安装Windows 10更新时有出现过错误吗?会不会是无法升级到最新的Windows 10版本?...