Log.d(“launch”, “启动一个协程”)
}
GlobalScope.async{
Log.d(“async”, “启动一个协程”)
}
}
}
然后运行app,点击按钮执行start()
方法。我们就可以在控制台上看到如下输出:
D/runBlocking: 启动一个协程
D/launch: 启动一个协程
D/async: 启动一个协程
哇
,so easy。协程原来这么简单,那我们接着继续往下走。上面提到过三种启动方式分别会的得到各自的返回信息。我们现在增加三个变量然后分别用协程进行赋值,同时进行输出:
private fun start(){
val runBlockingJob = runBlocking {
Log.d(“runBlocking”, “启动一个协程”)
}
Log.d(“runBlockingJob”, “$runBlockingJob”)
val launchJob = GlobalScope.launch{
Log.d(“launch”, “启动一个协程”)
}
Log.d(“launchJob”, “$launchJob”)
val asyncJob = GlobalScope.async{
Log.d(“async”, “启动一个协程”)
“我是返回值”
}
Log.d(“asyncJob”, “$asyncJob”)
}
然后运行,我们可以在控制台上看到如下输出:
D/runBlocking: 启动一个协程
D/runBlockingJob: 41
D/launchJob: StandaloneCoroutine{Active}@3b8b871
D/launch: 启动一个协程
D/async: 启动一个协程
D/asyncJob: DeferredCoroutine{Active}@63f265
也有可能是
D/runBlocking: 启动一个协程
D/runBlockingJob: 41
D/launchJob: StandaloneCoroutine{Active}@1344515
D/asyncJob: DeferredCoroutine{Active}@38c002a
D/async: 启动一个协程
D/launch: 启动一个协程
还有可能是
D/runBlocking: 启动一个协程
D/runBlockingJob: 41
D/launch: 启动一个协程
D/launchJob: StandaloneCoroutine{Active}@b94e973
D/async: 启动一个协程
D/ asyncJob: DeferredCoroutine{Active}@f7aa030
嗯哼,什么情况
怎么后面4条日志顺序还是随机的。没有看懂的童鞋,说明你没有仔细看上面的文字。
知识点来了,赶紧拿出你的小本本记下来,我们一个一个的来分析。
我们在上面提到过runBlocking
启动的是一个新的协程并阻塞调用它的线程,我们对比输出日志可以看到前两条runBlocking
的相关输出日志的位置顺序是不会变化的,这就证明我们之前所说的runBlocking
会阻塞调用它的线程,直到runBlocking
运行结束才继续往下执行。
接下来我们再继续往下看,我们看到后面四条日志是无序的,但是launchJob
始终在asyncJob
前面。而launch
和async
协程体内的日志输出是无序的。每执行一次看到的顺序都有可能跟之前的不一样。我们前面提到过launch
和async
都是启动一个协程但不会阻塞调用线程,所以launchJob
始终在asyncJob
前面(2个协程之间不是很明显,你们自己在尝试的时候,可以同时启动5个甚至更多协程去看日志输出)
而launch
和async
协程体内的日志是无序的,这是因为协程采用的是并发设计模式,所以launch
和async
的协程体内的log日志输出是无序方式,这就解释了launch
和async
都是启动一个协程但不会阻塞调用线程,同时也解释了log日志之间输出顺序之间的关系(这里描述是不严谨的,后面会补充
)。
难道就这样结束了吗?那你想的可就太简单了。刚才我们提到协程采用的是并发设计模式,多个协程并发执行的。那如果这个时候,我们把启动协程放在同一协程作用域下启动的是顺序又该是怎么样的呢? 大家可以先思考一下这个问题,回头我们再来看这个问题。