android - 即使没有 "suspend"关键字,Kotlin 协程为什么以及如何防止线程阻塞?

标签 android multithreading kotlin kotlin-coroutines

我在 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()应该已经阻塞了主线程。当涉及协程时,它怎么会不呢?协程是否有“拦截”这种低级交互的手段?

  • 谢谢

    最佳答案

    点赞post()View , launch() (通常)安排与当前执行位异步执行的工作。因此,您的 lambda 表达式中的代码传递给 launch()最终将在主应用程序线程上运行,就像 Runnable您提供给 post()最终将在主应用程序线程上运行。但是,您的 onCreate()函数将继续超过 launch() 的点做它应该做的任何其他事情。

    但是,就像 Runnable传递给 post()由于它在 run() 中所做的工作,它仍然会占用主应用程序线程,您的协程仍可能占用主应用程序线程。只是这项工作会比你直接在 onCreate() 中进行的工作晚。 .

    It's just that animations still work



    IIRC,在较新版本的 Android 上,动画本身在单独的“渲染”线程上进行处理。

    关于android - 即使没有 "suspend"关键字,Kotlin 协程为什么以及如何防止线程阻塞?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58474749/

    相关文章:

    c# - 并行运行时任务变慢

    multithreading - RabbitMQ - 每个路由键单个并发 worker

    android - 如何使用camerax前置摄像头保存正确的旋转图像?

    java - 如何在android keystore 中存储私钥?

    java - 让后台运行并持续关注网络连接的好方法是什么?

    java - 循环遍历 Activity 中的所有 "widgets"/元素

    android - 无法安装 HAXM(Android Studio、AMD 处理器)

    android - 图像解密不工作android

    .net - 如何检测.NET中的跨线程访问(强制线程关联)?

    kotlin - 接受者如何为状态添加值(value)并发送回发起者