Подвеска Coroutine полностью явная и первоклассная. Это происходит, когда вы вызываете suspendCoroutine()
или suspendCancellableCoroutine()
, передавая блок, который получает продолжение в качестве параметра.
Блок может делать с объектом продолжения все, что хочет, и когда кто-то где-то вызывает continuation.resume(resultValue()
, он возобновляет работу. Поток, с которого он возобновляет работу, изначально является потоком, который вызывает resume()
, но логика внутри resume
немедленно делегирует ответственному диспетчеру, который затем обычно передает возобновление другому потоку или пулу потоков.
Логика диспетчера снова первоклассна, и вы можете написать свой собственный диспетчер. Тем не менее, это почти никогда не требуется, потому что есть только несколько значимых способов сделать это, и Котлин уже поддерживает их.
Вы также можете просмотреть конкретный пример в коде , который демонстрирует скрытое использование suspendCoroutine
и coroutine.resume()
без слоя, который добавляет к нему Диспетчер.
Кстати, вы никогда не делегируете блокирующие операции «потокам ядра», чтобы сделать их неблокирующими. Асинхронные операции не блокируют ни один поток. На низком уровне, например, есть механизм селектора , который получает события от операций ввода-вывода, когда они завершаются. Он работает так же, как цикл обработки событий в потоке GUI.