0

如果我运行一个launch带有阻塞队列的阻塞,那么launch之后就不会运行其他的了。这只发生在 Android 4.1 上,我用 Android 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")
        }
    }
}

输出:

05-15 12:09:39.707 4337-4361/org.testcoroutines D/StandaloneCoroutine: TEST 1

TEST 3从不记录。但是,如果我用 替换“阻塞” launchthread它就可以工作。

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

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: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

任何想法为什么会发生这种情况以及如何解决它?

4

1 回答 1

3

ArrayBlockingQueue.take操作被阻塞。它阻塞调用者线程并且不允许它用于其他任何事情。在“小型”设备上,默认线程池中可能只有一个后台线程,当您阻止该线程时,不会发生任何其他有用的事情。协程旨在与不阻塞线程的非阻塞(异步)API 一起工作。

对于协程,您应该使用与阻塞队列为线程服务的目的大致相同的通道。通道不会阻塞调用者线程,而是暂停调用协程,从而允许将同一个线程用于多个正在运行的协程。

您可以通过示例在 kotlinx.coroutines 指南中找到有关通道的更多信息。

于 2018-05-16T15:14:59.407 回答