DispatchQueue je základní fronta frameworku Grand Central Dispatch (GCD) pro správu asynchronních úloh v iOS a macOS. Podle Apple Developer Documentation, 2026 DispatchQueue abstrahuje správu vláken od vývojáře pomocí serial a concurrent front. GCD automaticky distribuuje úlohy do systémového fondu vláken, čímž odpadá ruční vytváření a ničení vláken.
Hlavní body
DispatchQueue je objekt frameworku Grand Central Dispatch (GCD), který spravuje provádění úloh v systémových nebo vlastních frontách vláken. Grand Central Dispatch je nízkoúrovňová knihovna Apple, dostupná od iOS 4 a macOS 10.6, která zcela abstrahuje správu vláken od vývojáře. GCD využívá fond vláken operačního systému a automaticky škáluje počet vláken podle zatížení zařízení.
Vývojář nemusí ručně vytvářet a ničit vlákna — GCD přebírá tento úkol a poskytuje jednoduché API prostřednictvím DispatchQueue. Úloha ve formě closure (uzávěru) je odeslána do fronty pomocí metod sync nebo async. V prvním případě je volající vlákno blokováno až do dokončení úlohy, ve druhém — okamžitě pokračuje v provádění.
Podle Apple (2026) GCD využívá systémový fond vláken, který se přizpůsobuje počtu jader a aktuálnímu zatížení procesoru. Concurrent fronta nevytváří nové vlákno pro každou úlohu — GCD znovu používá vlákna z fondu, což minimalizuje režii vytváření vláken.
Grand Central Dispatch se skládá ze tří klíčových komponent: fronty (DispatchQueue), skupiny (DispatchGroup) a semafory (DispatchSemaphore). Fronta je hlavní prvek přijímající úlohy ve formě bloků kódu. DispatchGroup synchronizuje provádění více úloh a DispatchSemaphore omezuje přístup ke sdílenému zdroji na určitý počet vláken.
Každá fronta GCD je spojena s určitou třídou QoS (Quality of Service), která informuje systém o důležitosti úlohy. Systém používá QoS pro distribuci procesorového času mezi frontami, přičemž dává prioritu kritičtějším úlohám — například aktualizaci UI nebo zpracování dotyků uživatele.
Serial fronta provádí úlohy přísně sekvenčně, jednu po druhé. Pokud jsou do serial fronty vloženy tři úlohy, druhá začne až po úplném dokončení první. Serial fronty se používají pro synchronizaci přístupu ke sdíleným zdrojům — například k poli, které je upravováno z více částí kódu.
Concurrent fronta spouští více úloh současně a rozděluje je mezi dostupná vlákna ze systémového fondu. Úlohy v concurrent frontě se spouští v pořadí příchodu (FIFO), ale končí v náhodném pořadí, pokud se doba jejich provádění liší. Concurrent fronta nezaručuje pořadí dokončení — pouze pořadí spuštění.
| Parametr | Serial fronta | Concurrent fronta |
|---|---|---|
| Pořadí provádění | Přísně sekvenční | Paralelní |
| Počet vláken | Jedno | Několik z fondu GCD |
| Použití | Ochrana sdílených zdrojů | Nezávislé výpočty |
| Main queue | Ano (hlavní vlákno) | Ne |
| Riziko deadlocku | Vysoké při sync na stejné frontě | Nízké |
Serial fronta je ideální pro úlohy upravující sdílený stav — zápis do souboru, aktualizaci datového modelu nebo práci s Core Data. Použití serial fronty zaručuje, že dvě části kódu neupraví stejná data současně, čímž odpadá race condition bez dalších zámků.
Concurrent fronta je vhodná pro úlohy, které na sobě nezávisí: načítání více obrázků, paralelní síťové požadavky nebo dávkové zpracování dat. GCD automaticky rozhoduje, kolik úloh spustit současně, na základě počtu jader procesoru a aktuálního zatížení systému.
QoS (Quality of Service) — mechanismus GCD, který informuje operační systém o důležitosti a naléhavosti úlohy. Systém používá QoS pro plánování vláken: úlohy s vyšším QoS získávají více procesorového času a jsou spouštěny dříve. Hodnota QoS je předána při vytváření fronty nebo odesílání konkrétní úlohy.
V GCD je k dispozici pět tříd QoS. .userInteractive — nejvyšší priorita pro úlohy související s UI. .userInitiated — pro úlohy iniciované uživatelem. .utility — pro úlohy na pozadí se zobrazením průběhu. .background — pro úlohy neviditelné pro uživatele. .default — střední úroveň mezi userInitiated a utility, používá se ve výchozím nastavení.
Podle Apple (2026) je nesprávná volba QoS jednou z častých příčin problémů s výkonem. Spuštění stahování na pozadí s QoS .userInteractive odebírá zdroje UI, což způsobuje mikro-zasekávání v animacích. Doporučuje se zvolit nejnižší QoS, který stále poskytuje přijatelnou dobu provádění.
Při načítání obrázku pro okamžité zobrazení použijte .userInitiated — uživatel očekává výsledek. Pro přednačtení další obrazovky stačí .utility. Synchronizace na pozadí se serverem se provádí s .background, což minimalizuje dopad na aktivní úlohy.
DispatchGroup umožňuje sledovat dokončení skupiny úloh. Když jsou všechny úlohy ve skupině dokončeny, GCD zavolá obsluhu notify na zadané frontě. To je užitečné zejména při načítání více nezávislých zdrojů — dat profilu, seznamu přátel a nastavení — kdy rozhraní musí být aktualizováno až po obdržení všech dat.
DispatchGroup podporuje synchronní volání wait(), které blokuje aktuální vlákno až do dokončení všech úloh. To je výhodné, když kód nemůže pokračovat bez výsledků skupiny. Asynchronní varianta — notify() — volá closure na zadané frontě po dokončení všech úloh, aniž by blokovala volající vlákno.
DispatchSemaphore řídí přístup ke zdroji a omezuje počet současných přístupů. Semafory s počáteční hodnotou 3 umožňují spustit nejvýše tři paralelní úlohy. Při volání wait() se čítač snižuje, při signal() — zvyšuje. Pokud je čítač nulový, vlákno je blokováno až do uvolnění zdroje.
Podívejme se na tři praktické příklady použití DispatchQueue v Swift. První ukazuje základní async volání s návratem na hlavní vlákno, druhý — synchronizaci přes serial frontu, třetí — DispatchGroup pro paralelní požadavky.
DispatchQueue.main je serial fronta hlavního vlákna určená výhradně pro operace UI. Vždy ji používejte pro aktualizaci rozhraní po dokončení práce na pozadí.
let queue = DispatchQueue.global(qos: .userInitiated)
queue.async {
let data = self.fetchData()
DispatchQueue.main.async {
self.updateUI(with: data)
}
}
Vytvoření vlastní serial fronty s jedinečným identifikátorem synchronizuje přístup k měnitelnému poli. Všechny operace čtení a zápisu procházejí jednou frontou, čímž se eliminuje race condition.
let serialQueue = DispatchQueue(label: "com.app.items")
var items: [Int] = []
serialQueue.async {
items.append(1)
}
serialQueue.async {
let last = items.last
DispatchQueue.main.async {
print("Last item: \(last)")
}
}
DispatchGroup umožňuje spustit více úloh na concurrent frontě a obdržet oznámení o dokončení všech. To je užitečné při načítání dat pro obrazovku profilu.
let group = DispatchGroup()
let worker = DispatchQueue.global()
worker.async(group: group) { self.loadProfile() }
worker.async(group: group) { self.loadFriends() }
worker.async(group: group) { self.loadSettings() }
group.notify(queue: DispatchQueue.main) {
self.showCompleteUI()
}
Deadlock při volání sync na serial frontě — nejčastější chyba. Pokud úloha na serial frontě zavolá queue.sync na stejné frontě, vlákno je trvale blokováno. Fronta čeká na dokončení aktuální úlohy a úloha čeká na dokončení volání sync — klasický vzájemný zámek.
Všechny operace s UIKit musí být prováděny na hlavním vlákně. Xcode detekuje tyto chyby v režimu Debug pomocí Main Thread Checker. V Release sestavení vedou k nepředvídatelnému chování: animace se nespouštějí, UI se neaktualizuje, jsou možné crash.
Vytváření stovek vlastních front místo globálních front — antivzor. Každá fronta spotřebovává systémové zdroje. Pro většinu úloh stačí globální concurrent fronty s různým QoS a jedna-dvě serial fronty pro synchronizaci sdílených dat.
Při provádění výpočetně náročných cyklických úloh na frontě na pozadí bez autoreleasepool paměť roste až do konce celé smyčky. ARC uvolňuje objekty pouze při opuštění autorelease pool. Zabalte iterace smyčky do autoreleasepool { } pro včasné uvolnění paměti.
Často kladené otázky
OperationQueue je postavena na GCD, ale poskytuje API vyšší úrovně se závislostmi operací, KVO a podporou zrušení. DispatchQueue je nízkoúrovňová fronta pro jednoduché async úlohy bez správy závislostí.
GCD nepodporuje zastavení spuštěné úlohy. Metoda suspend() pozastavuje pouze nové úlohy, aktuální běží až do konce. Pro zrušení je nutná ruční kontrola příznaku uvnitř kódu úlohy.
Pro hlavní požadavek s okamžitým zobrazením výsledku — .userInitiated. Pro přednačtení dat — .utility. Pro synchronizaci na pozadí — .background.
GCD nestanovuje pevný počet vláken. Fond vláken se dynamicky škáluje podle zatížení, s ohledem na jádra procesoru, aktuální zatížení a QoS každé úlohy. Maximální počet je omezen systémem.
UIKit není thread-safe — všechny jeho třídy musí být volány pouze z hlavního vlákna. Porušení způsobuje nepředvídatelné chování, zmeškané aktualizace a crash v produkci.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také