Pull to refresh

Comments 10

Хорошая и большая статья, но есть все же несколько очень важных но:

  1. Не упомянут dispatcher main.immediate (а у него есть одно очень важное свойство, не просто так он используется в lifecycle scope, про viewmodel scope на память не помню). И из этого вытекает:

  2. Не рассказано про старт корутин, а это очень важно. И из этого вытекает:

  3. Корутин билдеры не используются для старта корутин, точнее не всегда используются - яркий пример это lazy старт корутин. Так же они не принимают блок кода который будет выполнен асинхронно - это управляется контекстом (dispatcher и scheduler)

  4. И самое главное!!! cancel() не прерывает и не прекращает выполнение coroutine, иначе не рекомендовали бы использовать yeld(). + Не рекомендовали прокидывать cancellation exception из try catch. Ну и cancelAndJoin() появился не просто так...

Вы правы, dispatcher main.immediate — это диспетчер, который может быть использован в контексте корутины. Он предназначен для немедленного выполнения задач в главном потоке. Данный диспетчер может быть полезен в ситуациях, когда необходимо выполнить корутину сразу же в основном потоке без задержки. Он часто используется в связке с lifecycle scope или viewmodel scope.

По поводу корутин-билдеров: в данной статье не рассматриваем, что происходит под капотом билдера, так как этот материал объемный и важно было донести суть того, что билдер обработает переданный ему блок кода(передаст в корутину) и запустит ее.

На счет cancel(): все верно, поэтому в статье приведен пример проверки — isActive внутри корутины, которая позволяет проверить, активен ли Job (не был ли отменен или завершен).

Не понял фразы начет Dispatchers.Unconfined - Корутина будет продолжена на том же потоке, на котором была запущена.

Возможно, неточно сформулирована мысль в отношении Dispatchers.Unconfined.

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

Получается корутины в Default в начале назначаются на поток но потом все его шаги строго привязаны к тому потоку? А это не вызывается проблем с балансировкой?

Корутина выполняется на диспатчере; а к диспатчеру привязан пул потоков.
Main - 1, IO - 64, Default - по количеству ядер CPU, Unconfirmed- все вместе. Можно и свой сделать.
При этом корутина может быть приостановлена в любой suspend точке (например delay, yield - тоже suspend fun) а после возвращения к выполнению - продолжить работу на любом другом потоке из пула.

Давайте рассмотрим на примере диспатчера из вашего вопроса (то же самое будет касаться и других диспатчеров):

  1. Допустим, при запуске корутины мы передаем Coroutine Context, а именно Dispatcher.Default, размер пула потоков которого равняется количеству ядер CPU.

  2. Корутина запускается на свободном потоке из пула потоков Dispatcher.Default.

  3. Когда корутина приостанавливается, она освобождает поток и он, скажем так, возвращается обратно в пул потоков Dispatcher.Default.

  4. Когда корутина продолжит свою работу, для нее будет назначен свободный поток из диспатчера Default, но не факт, что это будет тот же поток, на котором она работала раньше.

Я видимо неправильно прочитал ваш оригинальный коментарий. Я думал что вы имеете ввиду что выбор потока для последующих шагов это особенность именно Unconfined диспетчера.

Почему в 9 главе в первый код выдает:

tick 2

tick 1

tick 1

tick 2

А второй код:

tick 1

tick 2

tick 1

tick 2

?

Казалось бы всегда должен быть второй вариант, т.к. tick 2 вызывается на несколько миллисекунд (наносекунд?) позже.

В данном примере запущенные корутины работают параллельно друг другу и выполняются в разных потоках из пула потоков, предоставляемого Dispatchers.IO. Кроме того, когда корутина возобновляет свою работу (в данном примере после delay(1_000)), она может быть продолжена на любом из свободных потоков, представленных в пуле потоков в Dispatchers.IO. Порядок выполнения и вывода сообщений "tick 1" и "tick 2" не гарантирован и может меняться из-за асинхронной природы корутин и их запуска в разных потоках.

Sign up to leave a comment.

Articles