---
title: Многопоточное программирование
seo:
  title: Многопоточное программирование — Kotlin Developer
  description: Тема «Многопоточное программирование» для собеседования Kotlin Developer. Что такое Main Thread? Где вызывать сложные задачи?
---

[Все темы Kotlin Developer](/kotlin-developer)

## <strong>Что такое Main Thread?</strong> [#q-14bee738d69b816db710e099cf82982a]

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

:::note[Ссылки для изучения]

1. [Многопоточность в мобильной разработке](https://habr.com/ru/articles/739212/)
   :::

---

## <strong>Где вызывать сложные задачи?</strong> [#q-14bee738d69b81dd84caf2811ffae343]

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

:::note[Ссылки для изучения]

1. [Многопоточность в мобильной разработке](https://habr.com/ru/articles/739212/)
   :::

---

## <strong>Что представляют собой</strong> <code>Handler</code> <strong>и</strong> <code>Looper</code><strong>?</strong> [#q-14bee738d69b81ef84e5ddd60dadb731]

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

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

- <code>Handler</code> связывается с конкретным <code>Looper</code>'ом и
  используется для отправки сообщений в очередь сообщений, обрабатываемую этим
  <code>Looper</code>'ом, а также для планирования выполнения кода в контексте
  этого <code>Looper</code>'а.

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

:::note[Ссылки для изучения]

1. [Многопоточность в мобильной разработке](https://habr.com/ru/articles/739212/)
   :::

---

## <strong>Как гарантировано вызвать код на главном потоке?</strong> [#q-14bee738d69b81a0aa34f306447f2358]

Чтобы гарантированно вызвать код на главном потоке (UI-потоке) в Android, можно использовать <code>Handler</code> с <code>Looper</code>'ом, связанным с главным потоком. Например&#58;

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

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

:::note[Ссылки для изучения]

1. [Многопоточность в мобильной разработке](https://habr.com/ru/articles/739212/)
   :::

---

## <strong>Что представляют собой мьютекс, монитор, ключевое слово</strong> <code>synchronized</code> <strong>и</strong> <code>volatile</code><strong>?</strong> [#q-14bee738d69b818c90c0ee2ec59adb2d]

Определение терминов&#58;

- <strong>Мьютекс (Mutex)</strong>&#58; это средство синхронизации, используемое
  для предотвращения одновременного доступа к общему ресурсу из нескольких
  потоков. Только один поток может владеть мьютексом в любой момент времени.

- <strong>Монитор</strong>&#58; это абстрактное понятие, связанное с
  синхронизацией потоков. В контексте Java мониторы обычно ассоциируются с
  объектами. Каждый объект в Java имеет свой монитор, который можно использовать
  для синхронизации потоков.

- <strong>Ключевое слово synchronized</strong>&#58; это ключевое слово в Java,
  которое используется для синхронизации доступа к методам или блокам кода.
  Когда метод или блок кода помечен как synchronized, только один поток может
  выполнить его за раз.

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

:::note[Ссылки для изучения]

1. [Многопоточность в мобильной разработке](https://habr.com/ru/articles/739212/)
   :::

---

## <strong>Как управлять потоками в Kotlin и какие классы для этого используются?</strong> [#q-14bee738d69b81208ea6caf32602fe76]

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

1. <code>Thread</code>&#58; Класс для создания и управления потоками.

   ```kotlin
   val thread = Thread {
       // Код, выполняемый в потоке
   }
   thread.start()
   ```

1. <code>Executors</code>&#58; Для управления пулами потоков.

   ```kotlin
   val executor = Executors.newSingleThreadExecutor()
   executor.execute {
       // Код, выполняемый в потоке
   }
   ```

1. <code>Coroutines</code>&#58; Легковесные потоки, управляемые Kotlin.

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

:::note[Ссылки для изучения]

1. [Многопоточность в мобильной разработке](https://habr.com/ru/articles/739212/)
   :::

---

## <strong>Что такое синхронизация и как её реализовать в Kotlin?</strong> [#q-14bee738d69b812d93b9f40386dd5c08]

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

Пример&#58;

```kotlin
class Counter {
    private var count = 0

    @Synchronized
    fun increment() {
        count++
    }

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

:::note[Ссылки для изучения]

1. [Многопоточность в мобильной разработке](https://habr.com/ru/articles/739212/)
   :::

---

## <strong>Объясните разницу между</strong> <code>Coroutine</code> <strong>и</strong> <code>Thread</code> <strong>в Kotlin.</strong> [#q-14bee738d69b81c081c7ddaba6b57343]

Основная разница между <code>Coroutine</code> и <code>Thread</code>&#58;

- <code>Thread</code>&#58; Поток операционной системы, занимает больше ресурсов.
  Создание и переключение между потоками требует времени.

- <code>Coroutine</code>&#58; Легковесный поток, управляемый Kotlin. Занимает
  меньше ресурсов и позволяет проще управлять асинхронными задачами.

:::note[Ссылки для изучения]

1. [Многопоточность в мобильной разработке](https://habr.com/ru/articles/739212/)
   :::

---

## <strong>Какие проблемы могут возникнуть при работе с многопоточностью и как их избежать?</strong> [#q-14bee738d69b8195b935d78c118ff151]

Основные проблемы при работе с многопоточностью&#58;

{/* prettier-ignore */}
1. Гонки данных&#58; Несинхронизированный доступ из нескольких потоков к одной области памяти, когда хотя бы один доступ является записью.

    - Решение&#58; Использовать синхронизацию (например, <code>synchronized</code> или <code>ReentrantLock</code>).

1. <strong>Взаимоблокировка (</strong><code>Deadlock</code><strong>)</strong>&#58; Когда два или более потоков ждут освобождения ресурсов друг от друга.

    - Решение&#58; Избегать вложенной блокировки, использовать <code>tryLock</code> для предотвращения блокировок.

1. Активная блокировка, или livelock&#58; Потоки продолжают менять состояние, но полезная работа не продвигается.

    - Решение&#58; Контролировать и корректировать алгоритмы синхронизации.

1. <strong>Избыточное переключение контекста (</strong><code>Context Switching</code><strong>)</strong>&#58; Частые переключения между потоками могут снизить производительность.

    - Решение&#58; Оптимизировать количество потоков, использовать пулы потоков или корутины.

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

:::note[Ссылки для изучения]

1. [Многопоточность в мобильной разработке](https://habr.com/ru/articles/739212/)
   :::
