coroutine神奇又好用,那我要怎麽开始呢?
官方提供了两种方法,launch和 async
launch的意思,大概是我要这里创造新的coroutine,并在指定的Thread之中运行,这里是哪里呢?
只要是coroutinescope里面,或是suspend function都可以(因为suspend一定要在coroutineScope或suspend function里面执行)
而launch的特性是他不会在coroutine结束时返回值,多数情况都会以launch创建coroutine
start a new coroutine that is “fire and forget” — that means it won’t return the result to the caller.
val scope = CoroutineScope(rootJob)
scope.launch ( Dispatchers.IO ){
//code
}
//看原始码,我们写在coroutine里的代码块会被标记上suspend
fun CoroutineScope.launch {
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
}
那async要怎麽用?
当两个任务之间没有相互关系时,async并发可以让我们减少等待执行的时间,并回传deferred类型,因为无法确定非同步任务会在何时结束,不论是运算结果或是Exception,他都预期开发者会呼叫await()挂起函数,以获得回传值或是错误讯息,所以预设并不会丢出exception
val scope = CoroutineScope(rootJob)
scope.async {
}.await()
可以比较一下原始码
fun CoroutineScope.async() {
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> T
}: Deferred<T>
只看文字应该会觉得似懂非懂,这里我们再带个小范例
val task: (String) ->Unit = { Timber.d("longTimeTask in $it") }
fun longTimeTask(): (String) -> Unit {
return task
}
val scope = CoroutineScope(rootJob)
val notRelateWork1 = scope.async {
Timber.d("in async 1")
longTimeTask()
}
val notRelateWork2 = scope.async {
longTimeTask().invoke("async 2")
Timber.d("in async 2")
}
scope.launch {
Timber.d("in launch")
notRelateWork1.await().invoke("async 1") //(String) -> Unit
notRelateWork2.await() //Unit
}
//in async 1
//longTimeTask in async 2
//in async 2
//in launch
//longTimeTask in async 1
这里的顺序非常重要,尽管我们需要呼叫await,来拿到async回传参数,但在async回传值之前的代码会先被执行,而在async里面默认是回传最後一行的值,所以我搭配lambda,大家应该很容易就能看出呼叫执行task的地方差异了
重点:launch和async很大的差别在於
Warning: A big difference between launch and async is how they handle exceptions. async expects that you will eventually call await to get a result (or exception) so it won’t throw exceptions by default. That means if you use async to start a new coroutine it will silently drop exceptions.
我们介绍完了await()和async的基本知识,但刚刚提过 当两个任务之间没有相互关系时,async并发可以让我们减少等待执行的时间, 具体来说,还是看code比较实际
今天如果用launch要等两秒,但async并发只要等1秒多一点,今天如果是有10个任务,launch要等10秒,但async一样是一秒多
suspend delay1000():Int{
delay(1000)
//pretend a api call
return 1
}
val time = measureTimeMillis {
val one = async { delay1000() }
val two = async { delay1000() }
println("The answer is ${one.await() + two.await()}")
}
println("Completed in $time ms")
//或分开写
val time = measureTimeMillis {
println("The answer is ${concurrentSum()}")
}
println("Completed in $time ms")
suspend fun concurrentSum(): Int = coroutineScope {
val one = async { delay1000() }
val two = async { delay1000() }
one.await() + two.await()
}
我实在找不到图说明这个步骤,用文字解释就是在delay1000(),里面的delay是suspend function,在launch里面时,suspend会依顺序触发,而在async代码执行到那里可被挂起,让thread可以先执行其他任务,当delay()结束後,会切回delay後面,继续执行其他代码
刚才讲到了代码的执行顺序,但如果我们希望在呼叫的时候才执行,有没有像 kotlin lazy的方法呢?有,也是lazy
我觉得很清楚了,应该不用解释吧
launch(start = CoroutineStart.LAZY) { delay1000() }
惰性的并发
只有通过 await 或者在 Job 的 start 函数调用的时候协程才会启动
val time = measureTimeMillis {
val one = async(start = CoroutineStart.LAZY) { delay1000() }
val two = async(start = CoroutineStart.LAZY) { delay1000() }
// 执行一些计算
one.start() // 启动第一个
two.start() // 启动第二个
println("The answer is ${one.await() + two.await()}")
}
println("Completed in $time ms")
要注意,如果不用start只用await,async coroutine会依序启动,而不会变成并发启动
当我们开启一个coroutine後,他就是 thread吗?
不对不对,我们之前讲过,kotlin 的coroutine只是一个线程框架,他是将线程包装成方便的版本,launch不是 thread,Dispatcher也不是thread,而这段Code实际上会是这样
val scope = CoroutineScope(rootJob)
scope.launch ( Dispatchers.IO ){
//code
}
//变成
handler.post{
//code from launch block
//launch里面的代码
}
launch和Dispatcher都不是thread本身,他们是将任务透过handler post到 thread 的looper里面。
参考连结:
必看
中文文档
android文档
英文async文档
github async 文档
中秋节来个应景梗图,中秋节快乐
放假太爽,day 5打成day 4,回来更新
<<: Day 05 - 行前说明 — UI 元件分类你知多少?
那麽昨天既然讲完了 get 那麽今天就来 post 一下 为了做到後端的功能 所以本次会以 Json...
在社交工程的攻击中,我们最常见的也莫过於电子邮件钓鱼 电子邮件钓鱼也被列为主要进行社交工程演练的项目...
一、前言 既然是全端工程师,就也带一下後端程序语言与架构上的基础内容。因为现职公司使用的是ASP...
什麽是 Latch ? 前几篇在 if-else 以及 case 语句时有提到 latch,那什麽是...
一. LSTM的问题 LSTM虽然非常强大,但LSTM也是有一个问题,就是计算时间较久导致执行速度较...