Перейти к содержимому
На этой странице

Многопоточное программирование

Все темы Kotlin Developer

Что такое Main Thread?

В Android главный поток обрабатывает события и обновляет UI. Длительные вычисления и блокирующий ввод-вывод выносят с него, чтобы интерфейс оставался отзывчивым и не возникал ANR.


Где вызывать сложные задачи?

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


Что представляют собой Handler и Looper?

Handler и Looper являются частями механизма обработки сообщений в Android.

  • Looper обрабатывает очередь сообщений своего потока. Он есть у главного потока Android и может быть создан у фонового потока.

  • Handler связывается с конкретным Looper’ом и используется для отправки сообщений в очередь сообщений, обрабатываемую этим Looper’ом, а также для планирования выполнения кода в контексте этого Looper’а.

Handler направляет задачи в поток соответствующего Looper. Сам по себе Handler не переносит работу в фон: Handler с главным Looper выполнит её на UI-потоке.


Как гарантировано вызвать код на главном потоке?

Чтобы гарантированно вызвать код на главном потоке (UI-потоке) в Android, можно использовать Handler с Looper’ом, связанным с главным потоком. Например:

Handler mainHandler = new Handler(Looper.getMainLooper());
mainHandler.post(() -> {
    // Код, который нужно выполнить на главном потоке
});

Этот код гарантирует, что переданный блок выполнится на главном потоке.


Что представляют собой мьютекс, монитор, ключевое слово synchronized и volatile?

Определение терминов:

  • Мьютекс (Mutex): это средство синхронизации, используемое для предотвращения одновременного доступа к общему ресурсу из нескольких потоков. Только один поток может владеть мьютексом в любой момент времени.

  • Монитор: это абстрактное понятие, связанное с синхронизацией потоков. В контексте Java мониторы обычно ассоциируются с объектами. Каждый объект в Java имеет свой монитор, который можно использовать для синхронизации потоков.

  • Ключевое слово synchronized: это ключевое слово в Java, которое используется для синхронизации доступа к методам или блокам кода. Когда метод или блок кода помечен как synchronized, только один поток может выполнить его за раз.

  • Volatile в Java и @Volatile в Kotlin/JVM обеспечивают видимость записи другим потокам и определённые гарантии порядка. Они не делают составные операции вроде count++ атомарными; для этого нужна синхронизация или атомарный тип.


Как управлять потоками в Kotlin и какие классы для этого используются?

В Kotlin для управления потоками можно использовать:

  1. Thread: Класс для создания и управления потоками.

    val thread = Thread {
        // Код, выполняемый в потоке
    }
    thread.start()
  2. Executors: Для управления пулами потоков.

    val executor = Executors.newSingleThreadExecutor()
    executor.execute {
        // Код, выполняемый в потоке
    }
  3. Coroutines: Легковесные потоки, управляемые Kotlin.

    GlobalScope.launch {
        // Код, выполняемый в корутине
    }

Что такое синхронизация и как её реализовать в Kotlin?

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

Пример:

class Counter {
    private var count = 0

    @Synchronized
    fun increment() {
        count++
    }

    @Synchronized
    fun getCount(): Int {
        return count
    }
}

Объясните разницу между Coroutine и Thread в Kotlin.

Основная разница между Coroutine и Thread:

  • Thread: Поток операционной системы, занимает больше ресурсов. Создание и переключение между потоками требует времени.

  • Coroutine: Легковесный поток, управляемый Kotlin. Занимает меньше ресурсов и позволяет проще управлять асинхронными задачами.


Какие проблемы могут возникнуть при работе с многопоточностью и как их избежать?

Основные проблемы при работе с многопоточностью:

  1. Гонки данных: Несинхронизированный доступ из нескольких потоков к одной области памяти, когда хотя бы один доступ является записью.

    • Решение: Использовать синхронизацию (например, synchronized или ReentrantLock).
  2. Взаимоблокировка (Deadlock): Когда два или более потоков ждут освобождения ресурсов друг от друга.

    • Решение: Избегать вложенной блокировки, использовать tryLock для предотвращения блокировок.
  3. Активная блокировка, или livelock: Потоки продолжают менять состояние, но полезная работа не продвигается.

    • Решение: Контролировать и корректировать алгоритмы синхронизации.
  4. Избыточное переключение контекста (Context Switching): Частые переключения между потоками могут снизить производительность.

    • Решение: Оптимизировать количество потоков, использовать пулы потоков или корутины.

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

Собеседования: Kotlin

Смотри записи интервью, узнай, какие вопросы задают и как отвечают кандидаты.

Вопросы и ответы

Не нашли ответ? Напишите мне в чат. Я делаю Шпаргалку и сам отвечаю на сообщения. Расскажите, что не работает или чего вам не хватает. Может, смогу сразу взять это в работу.

Откуда взяты вопросы?

Из реальных собеседований. Основой подборки стал опыт Вадима Новосёлова: он проходил интервью и записывал вопросы. Подробнее о материалах.

Насколько эти вопросы актуальны?

Эти вопросы встречались нам на реальных собеседованиях в 2025 году. Мы регулярно проходим собеседования и пополняем подборку новыми вопросами. Основы профессии и ключевые технологии остаются востребованными годами, а детали конкретных инструментов и версий стоит сверять с текущей документацией.

На какой уровень рассчитана подборка?

Мы проходили собеседования на вакансии уровня Middle+, а иногда и на Senior-позиции. Вопросы из этих интервью вошли в подборку. Направления работы: Kotlin-разработчик, Android-разработчик, Backend-разработчик на Kotlin. Глубина обсуждения зависит от вакансии: будь готов объяснить основную идею, привести практический пример и разобрать ограничения и альтернативы решения.

Этот вопрос точно будет на моём собеседовании?

Гарантии нет: набор вопросов зависит от компании, задач команды, уровня вакансии и самого интервьюера. Эти вопросы уже встречались на реальных собеседованиях, но на твоём интервью ту же тему могут проверить другой формулировкой, практической задачей или обсуждением твоего опыта. Используй подборку, чтобы разобраться в теме: объясняй идею своими словами, приводи примеры и готовься обсудить ограничения и альтернативы решения. Так будет проще ответить и на знакомый вопрос, и на неожиданные уточнения.