Coroutines Android 4.1: последующие запуски не работают после блокировки очереди - PullRequest
0 голосов
/ 15 мая 2018

Если я запускаю 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 никогда не регистрируется.Однако, если я заменю «блокирование» 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: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

Есть идеи, почему это может происходить и как это исправить?

1 Ответ

0 голосов
/ 16 мая 2018

ArrayBlockingQueue.take операция блокировка . Он блокирует поток invoker и не позволяет использовать его для чего-либо еще. На «маленьких» устройствах в пуле потоков по умолчанию может быть только один фоновый поток, и когда вы блокируете этот поток, больше ничего полезного не может произойти. Сопрограммы предназначены для работы с неблокирующими (асинхронными) API, которые не блокируют потоки.

С сопрограммами вы должны использовать каналов , которые служат примерно той же цели для сопрограмм, что и очереди блокировки для потоков. Каналы не блокируют поток вызова, но приостанавливают вызова сопрограммы, что позволяет использовать один и тот же поток для нескольких запущенных сопрограмм.

Дополнительную информацию о каналах можно найти в Руководстве по kotlinx.coroutines на примере .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...