Когда очередь (DispatchQueue) в GCD получает собственный поток для выполнения?

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

Ответ

DispatchQueue сама по себе не является потоком. Это абстракция для управления задачами. Потоки из пула GCD динамически назначаются очередям системой для выполнения их задач. Главное правило: очередь получает поток, когда в ней есть задача для выполнения, и система может выделить ресурс.

Как это работает:

  • Серийная очередь (Serial): Задачи выполняются строго по одной. Для их выполнения системе обычно достаточно одного потока из пула, который может использоваться повторно для разных задач этой очереди.

    let serialQueue = DispatchQueue(label: "com.example.serial")
    serialQueue.async {
        // Эта задача будет выполнена на каком-то фоновом потоке из пула GCD.
        print(Thread.current)
    }
  • Конкурентная очередь (Concurrent): Задачи могут выполняться параллельно. Система может создать или выделить несколько потоков для одновременного выполнения задач из этой очереди.

    let concurrentQueue = DispatchQueue(label: "com.example.concurrent", attributes: .concurrent)
    for i in 1...5 {
        concurrentQueue.async {
            // Эти 5 задач могут выполняться на разных потоках одновременно.
            print("Task (i) on (Thread.current)")
        }
    }

Особые случаи:

  • Главная очередь (DispatchQueue.main): Всегда привязана к единственному главному потоку приложения. Не использует пул потоков.
  • Глобальные очереди (DispatchQueue.global(qos:)): Это предопределенные конкурентные очереди, которые используют общий пул потоков GCD.

Вывод: Поток не «принадлежит» очереди. Очередь — это планировщик задач, который получает потоки из общего пула по мере необходимости для выполнения своей работы.