Какие типы очередей доступны в Grand Central Dispatch (GCD) в iOS?

«Какие типы очередей доступны в Grand Central Dispatch (GCD) в iOS?» — вопрос из категории Многопоточность, который задают на 32% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В GCD (Grand Central Dispatch) в iOS/Swift существует два основных типа очередей, классифицируемых по способу выполнения задач:

1. Последовательные очереди (Serial Queues)

Задачи выполняются строго одна за другой в порядке добавления.

  • Главная очередь (Main Queue): Глобальная последовательная очередь, связанная с основным потоком. Все операции с UI должны выполняться на ней.
    DispatchQueue.main.async {
        self.label.text = "Updated" // Безопасное обновление UI
    }
  • Пользовательские последовательные очереди (Custom Serial Queues): Создаются разработчиком.
    let serialQueue = DispatchQueue(label: "com.app.serialQueue") // По умолчанию .serial
    serialQueue.async { print("Task 1") }
    serialQueue.async { print("Task 2") } // "Task 2" начнется только после завершения "Task 1"

2. Параллельные очереди (Concurrent Queues)

Задачи могут выполняться одновременно на нескольких потоках.

  • Глобальные параллельные очереди (Global Concurrent Queues): Системные очереди с разными уровнями приоритета (Quality of Service - QoS). QoS Приоритет Назначение
    .userInteractive Высший Анимации, мгновенный отклик на действия пользователя.
    .userInitiated Высокий Задачи, инициированные пользователем, требующие быстрого результата.
    .default Средний Задачи по умолчанию.
    .utility Низкий Длительные задачи (загрузка, вычисления) с индикатором прогресса.
    .background Самый низкий Фоновые задачи, невидимые пользователю (синхронизация, чистка).
    DispatchQueue.global(qos: .utility).async {
        let data = self.loadDataFromNetwork() // Долгая задача
        DispatchQueue.main.async { self.updateUI(with: data) } // Возврат на main
    }
  • Пользовательские параллельные очереди (Custom Concurrent Queues): Создаются разработчиком.
    let concurrentQueue = DispatchQueue(label: "com.app.concurrent", attributes: .concurrent)
    concurrentQueue.async { print("Task A") }
    concurrentQueue.async { print("Task B") } // "Task A" и "Task B" могут выполняться параллельно