Что происходит с потоком, когда его RunLoop не имеет событий для обработки?

«Что происходит с потоком, когда его RunLoop не имеет событий для обработки?» — вопрос из категории Многопоточность, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Когда у RunLoop (цикла событий) потока нет готовых к обработке источников (sources), таймеров (timers) или наблюдателей (observers), он переходит в режим сна.

Механизм работы:

  1. RunLoop завершает текущую итерацию.
  2. Поток, на котором работает RunLoop, приостанавливается ядром ОС.
  3. Это приводит к нулевому или минимальному использованию CPU, экономя заряд батареи.
  4. RunLoop «просыпается» автоматически при появлении нового события (например, сетевого пакета, срабатывания таймера, ручного пробуждения) или по истечении заданного таймаута.

Пример с таймаутом:

let runLoop = RunLoop.current
let deadline = Date(timeIntervalSinceNow: 5.0) // Таймаут 5 секунд

// RunLoop будет работать до дедлайна, но уснет, если не будет событий.
runLoop.run(until: deadline)

Особенности для разных потоков:

  • Главный поток (Main Thread): Его RunLoop (RunLoop.main) работает всегда, так как постоянно получает события от системы (касания, обновления UI, таймеры). Он никогда не завершается.
  • Фоновые потоки: RunLoop фонового потока по умолчанию не запущен. Если вы запустите его (например, для обработки сетевых сокетов), он может завершиться (run метод вернет управление), когда все источники событий будут удалены, и поток завершит выполнение.