协同路由Android 4.1:阻塞队列后后续启动不起作用

协同路由Android 4.1:阻塞队列后后续启动不起作用,android,kotlin,blockingqueue,kotlinx.coroutines,Android,Kotlin,Blockingqueue,Kotlinx.coroutines,如果我运行了一个launch,其中包含一个阻塞队列,那么之后将不会运行其他launch。这只发生在安卓4.1上,我用安卓6.0.1和7.0测试的其他设备工作正常。下面是一个例子: class MainActivity : AppCompatActivity() { private val blockingQueue = ArrayBlockingQueue<String>(10) override fun onCreate(savedInstanceState:

如果我运行了一个
launch
,其中包含一个阻塞队列,那么之后将不会运行其他
launch
。这只发生在安卓4.1上,我用安卓6.0.1和7.0测试的其他设备工作正常。下面是一个例子:

class MainActivity : AppCompatActivity() {

    private val blockingQueue = ArrayBlockingQueue<String>(10)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        launch {
            Log.d(javaClass.simpleName, "TEST 1")
        }
        launch {
            blockingQueue.take().run {
                Log.d(javaClass.simpleName, "TEST 2")
            }
        }
        launch {
            Log.d(javaClass.simpleName, "TEST 3")
        }
    }
}
测试3
从未记录。但是,如果我将“阻塞”
launch
替换为
thread
,它就会工作

如果我通过在队列上放置一个元素来解除对它的阻塞,那么其余的启动现在会运行

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    launch {
        Log.d(javaClass.simpleName, "TEST 1")
    }
    launch {
        blockingQueue.take().run {
            Log.d(javaClass.simpleName, "TEST 2 $this")
        }
    }
    launch {
        Log.d(javaClass.simpleName, "TEST 3")
    }
    thread {
        Thread.sleep(2000)
        Log.d(javaClass.simpleName, "TEST WAKE UP")
        blockingQueue.put("WAKE UP!")
    }
}
输出:

05-15 12:09:39.707 4337-4361/org.testcoroutines D/StandaloneCoroutine: TEST 1
05-15 12:10:33.367 4471-4492/org.testcoroutines D/StandaloneCoroutine: TEST 1
05-15 12:10:35.387 4471-4493/org.testcoroutines D/MainActivity: TEST WAKE UP
05-15 12:10:35.387 4471-4492/org.testcoroutines D/String: TEST 2 WAKE UP!
05-15 12:10:35.387 4471-4492/org.testcoroutines D/StandaloneCoroutine: TEST 3

知道为什么会发生这种情况以及如何修复它吗?

ArrayBlockingQueue.take操作正在阻塞。它阻塞了调用程序线程,不允许它用于其他任何事情。在“小型”设备上,默认线程池中可能只有一个后台线程,当您阻止该线程时,其他任何有用的事情都不会发生。协同路由设计用于使用不阻塞线程的非阻塞(异步)API

对于协同路由,您应该使用与阻塞队列用于线程的目的大致相同的通道。通道不阻塞调用程序线程,而是挂起调用协同路由,从而允许将同一线程用于多个正在运行的协同路由


您可以在。

阵列锁定队列中找到有关频道的详细信息。take
操作正在阻塞。它阻塞了调用程序线程,不允许它用于其他任何事情。在“小型”设备上,默认线程池中可能只有一个后台线程,当您阻止该线程时,其他任何有用的事情都不会发生。协同路由设计用于使用不阻塞线程的非阻塞(异步)API

对于协同路由,您应该使用与阻塞队列用于线程的目的大致相同的通道。通道不阻塞调用程序线程,而是挂起调用协同路由,从而允许将同一线程用于多个正在运行的协同路由


你可以在中找到有关频道的更多信息。

我怀疑这样的事情,非常感谢你的确认,罗曼。我怀疑这样的事情,非常感谢你的确认,罗曼。