【发布时间】:2019-10-20 15:58:55
【问题描述】:
我在 Android 应用中使用协程时遇到了一些意外行为。
假设我有以下函数,它不是“挂起”。它启动工作线程并阻塞调用线程,直到所有工作线程终止:
fun doSomething() : Result {
// producers init thread
Thread {
for (i in 0 until NUM_OF_MESSAGES) {
startNewProducer(i) // each producer is a thread
}
}.start()
// consumers init thread
Thread {
for (i in 0 until NUM_OF_MESSAGES) {
startNewConsumer() // each consumer is a thread
}
}.start()
synchronized(lock) {
while (numOfFinishedConsumers < NUM_OF_MESSAGES) {
try {
(lock as java.lang.Object).wait()
} catch (e: InterruptedException) {
return@synchronized
}
}
}
synchronized(lock) {
return Result(
System.currentTimeMillis() - startTimestamp,
numOfReceivedMessages
)
}
}
我知道(lock as java.lang.Object).wait()很丑,我最好用ReentrantLock,但我故意想掉到最原始的水平。
现在,如果我在没有协程的情况下从 Android 的主线程执行此函数,它会阻塞调用线程(预期行为):
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
someObject.doSomething()
}
但是,如果我只是将它包装在一个也在主线程上执行的协程中,则主线程不再被阻塞,但功能保持不变:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
CoroutineScope(Dispatchers.Main).launch {
val result = someObject.doSomething()
}
}
两个问题:
- 我认为为了让协程工作,函数应该是“挂起”,但这里不是这样。那么,“暂停”又有什么意义呢?
- 调用
(lock as java.lang.Object).wait()应该已经阻塞了主线程。当涉及协程时,它怎么会不呢?协程是否有“拦截”这种低级交互的手段?
谢谢
【问题讨论】:
-
如果你使用
findViewById<View>(android.R.id.content).post { val result = someObject.doSomething() },你会得到同样的结果吗?launch()与post()一样,设置将来要在主应用程序线程上完成的工作,因此当前回调的其余部分可以继续进行(即,在您的情况下,onCreate()的其余部分)。请参阅this 了解更多信息。 -
@CommonsWare,是的,你是对的。我进一步研究了它,主线程确实被阻塞了。只是动画仍然有效,所以它看起来就像一切都是有生命的,这让我问了这个问题。所以,它与协程无关。能否请您发布一个简短的答案,以便我接受?
标签: android multithreading kotlin kotlin-coroutines