Обновить

Собеседование. Часть 4: Корутины — от иллюзии потоков до Structured Concurrency и обработки ошибок

Многопоточность вызывает мандраж. В Android на смену RxJava пришли Kotlin Coroutines. За их лаконичным синтаксисом скрывается жесткая архитектура. Мой следующий блок вопросов проверяет, понимает ли кандидат, что именно происходит под капотом привычного launch.

Уровень 1: Иллюзия потоков (База)

Начинаю с провокации: «Корутина — это просто легковесный поток?»

Многие кивают, и это ловушка. Правильный ответ: Нет, это блок кода, умеющий приостанавливать работу (suspend) и возобновляться позже. На одном Main Thread могут поочередно работать тысячи корутин, не блокируя его. Это кооперативная многозадачность. Если кандидат отличает блокировку Thread.sleep от delay, базовый тест пройден.

Уровень 2: Кто за рулем? (Scope и Job)

Усложняем: «Мы запустили сетевой запрос. Юзер закрыл экран. Как избежать утечки памяти?»

Продвинутый кандидат назовет CoroutineScope и Job. Job управляет жизненным циклом задачи, а Scope — ее область видимости. Обязательный вопрос: «В чем фишка viewModelScope?» Ожидаемый ответ: он жестко привязан к ViewModel и автоматически вызывает cancel() дочерним корутинам в onCleared().

class MyViewModel : ViewModel() {
    fun loadData() {
        viewModelScope.launch { 
            val data = api.fetchData() // Отменится сам при смерти ViewModel
        }
    }
}

Уровень 3: Эффект домино (Structured Concurrency)

Меняем условия: «Запущено несколько задач в viewModelScope. Одна упала с Exception. Что будет?»

Джуны часто пишут try-catch внутри launch. Но истинный эксперт знает про Structured Concurrency. Корутины связаны иерархией. Если "ребенок" падает, он отменяет родителя (наш launch). Родитель умирает и отменяет остальных детей. В итоге молча упадет весь viewModelScope. Блок try-catch внутри вложенного launch здесь абсолютно бесполезен — исключение просто пробивает иерархию Job.

Уровень 4: Изоляция катастрофы (SupervisorJob)

Финальный босс: «Как защитить родительский scope от падения одной дочерней корутины?»

Здесь эксперт должен использовать supervisorScope. Его суперспособность — изоляция ошибок: смерть одной корутины не убивает соседей по scope.

class MyViewModel : ViewModel() {
    fun loadData() {
        viewModelScope.launch { 
            val data = api.fetchData() // Отменится сам при смерти ViewModel
        }
    }
}

А для глобальной обработки непойманных исключений (чтобы не крашнулось всё приложение) кандидат должен упомянуть CoroutineExceptionHandler, который передается в контекст корневой корутины.

Резюме: Суровая реальность против тепличного кода

Корутины расслабляют своим красивым синтаксисом. Для меня на интервью важно увидеть, что человек понимает последствия своих архитектурных решений.

В мобильной (и особенно Automotive) разработке сеть нестабильна. Машина заезжает в альпийский тоннель, связь обрывается, и один упавший сетевой запрос погоды не должен утянуть за собой весь модуль навигации из-за неправильно настроенной иерархии Job. Именно умение строить отказоустойчивые системы отличает кодера от инженера, которому можно смело доверить продакшен.

Теги:
+1
Комментарии0

Я запустил 100 ИИ‑агентов, чтобы они меня взломали. Пять раз у них получилось

Около сотни ИИ-агентов получили простую задачу — взломать аккаунты человека, зная только его имя. Я проверил это на себе: за пять часов агенты пять раз добились успеха, используя уязвимости старых проектов и слабые пароли. В статье рассказываю, как действовали агенты, сколько стоил эксперимент и почему подобные атаки вскоре могут стать массовыми.

Я запустил 100 ИИ‑агентов, чтобы они меня взломали. Пять раз у них получилось

Публикации