文章19 | 阅读 10452 | 点赞0
private suspend fun intValue1(): Int {
delay(1000)
return 1
}
private suspend fun intValue2(): Int {
delay(2000)
return 2
}
fun main() = runBlocking {
val elapsedTime = measureTimeMillis {
val value1 = intValue1()
val value2 = intValue2()
println("the result is ${value1 + value2}")
}
println("the elapsedTime is $elapsedTime")
}
先介绍一下measureTimeMillis{}:
/**
* Executes the given [block] and returns elapsed time in milliseconds.
*/
public inline fun measureTimeMillis(block: () -> Unit): Long {
val start = System.currentTimeMillis()
block()
return System.currentTimeMillis() - start
}
用来计算代码的执行时间的简便方法。然后来看输出结果:
the result is 3
the elapsedTime is 3018
这个例子想要说明什么问题呢?要想实现功能A,需要依赖于功能B和功能C的结果,如果功能B和功能C之间又有依赖关系,那么只能B和C顺序执行;但是如果B和C是完全独立的,那么B和C就可以同时进行,从而缩短实现功能A所需时间。就好像本例中的intValue1()和intValue2(),它们是完全独立的,但是从运行结果来看,耗费的时间是intValue1()的时间 + intValue2()的时间。那么怎么实现协程的高效并发呢?
fun main() = runBlocking {
val elapsedTime = measureTimeMillis {
val value1 = async { intValue1() }
val value2 = async { intValue2() }
println("the result is ${value1.await() + value2.await()}")
}
println("the elapsedTime is $elapsedTime")
}
private suspend fun intValue1(): Int {
delay(1000)
return 1
}
private suspend fun intValue2(): Int {
delay(2000)
return 2
}
输出结果为:
the result is 3
the elapsedTime is 2016
从结果上看,所耗时间变短了,执行效率也就提高了。
public fun <T> CoroutineScope.async(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> T
): Deferred<T>
Creates a coroutine and returns its future result as an implementation of [Deferred].
The running coroutine is cancelled when the resulting deferred is [cancelled][Job.cancel].
通过aysnc的方法签名以及它的文档注释,我们可以得知:
至此,我们创建协程的方式就有了五种:
那么Deferred到底是个什么东东?它和Job之间又有怎样的联系和区别?
public interface Deferred<out T> : Job
Deferred value is a non-blocking cancellable future — it is a [Job] with a result
从类的层次结构上看,Deferred是Job的子接口;从功能上来看,Deferred就是带返回结果的Job。
Awaits for completion of this value without blocking a thread and resumes when deferred computation is complete,returning the resulting value or throwing the corresponding exception if the deferred was cancelled
/**
* Defines start options for coroutines builders.
* It is used in `start` parameter of [launch][CoroutineScope.launch], [async][CoroutineScope.async], and other coroutine builder functions.
*
* The summary of coroutine start options is:
* * [DEFAULT] -- immediately schedules coroutine for execution according to its context;
* * [LAZY] -- starts coroutine lazily, only when it is needed;
* * [ATOMIC] -- atomically (in a non-cancellable way) schedules coroutine for execution according to its context;
* * [UNDISPATCHED] -- immediately executes coroutine until its first suspension point _in the current thread_.
*/
public enum class CoroutineStart {
DEFAULT,
LAZY,
ATOMIC,
UNDISPATCHED
}
这个参数在launch里面也有,表达的含义是一致的。
我们现在试一下LAZY的使用:
fun main() = runBlocking {
val elapsedTime = measureTimeMillis {
val intValue1 = async(start = CoroutineStart.LAZY) { intValue1() }
val intValue2 = async(start = CoroutineStart.LAZY) { intValue2() }
println("hello world")
val result1 = intValue1.await()
val result2 = intValue2.await()
println("the result is : ${result1 + result2}")
}
println("elapsedTime = $elapsedTime")
}
private suspend fun intValue1(): Int {
delay(1000)
return 15
}
private suspend fun intValue2(): Int {
delay(2000)
return 20
}
hello world
the result is : 35
elapsedTime = 3018
一旦添加了这个参数之后,我们会发现,async的并发失效了。结合前面的阐述,我们不难得出结论:由于CoroutineStart.LAZY的作用,我们async启动的两个协程并没有立即执行。而是直到调用await方法之后,才开始执行,而await又是会去等待结果,自然需要等待intValue1协程执行完毕后,遇到intValue2.await(),才会触发intValue2协程的执行,又要去等待。那么,async的并发也就失效了。
fun main() = runBlocking {
val elapsedTime = measureTimeMillis {
val intValue1 = async(start = CoroutineStart.LAZY) { intValue1() }
val intValue2 = async(start = CoroutineStart.LAZY) { intValue2() }
println("hello world")
intValue1.start()
intValue2.start()
val result1 = intValue1.await()
val result2 = intValue2.await()
println("the result is : ${result1 + result2}")
}
println("elapsedTime = $elapsedTime")
}
private suspend fun intValue1(): Int {
delay(1000)
return 15
}
private suspend fun intValue2(): Int {
delay(2000)
return 20
}
我们可以通过Deferred的start方法,手动触发协程的执行,输出结果如下:
hello world
the result is : 35
elapsedTime = 2013
换句话说,使用了CoroutineStart.LAZY参数之后,协程不会立马执行,直到调用了start()或await()才会触发协程的调度。
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/xlh1191860939/article/details/104981066
内容来源于网络,如有侵权,请联系作者删除!