Swift-GCD
Introduction
When we use network requesting, always use escaping closure to resolve the data passed from net to our UI, though it generally works, but when getting into some intricate cases, we need to use nested clousure, which is not elegant, so study Threading Control Tech is useful for us to code better.
For example, we need to request a Image from internet, we can request data in the background, and allow UI moves quickly in the main thread, after fetched data, refresh the Image Control in main thread.
What Is GCD
From Swift3 we really step into the world of Multi Threading Coding, where we have elegant grammer unlike the infrastructure developing with C in the past, Apple provided brand new grammer for us. However that is 3 or 4 years ago, now we just use several lines we can complete our tasks.
GCD is the logogram of Grand Central Dispatch, the main part of it is Dispatch Queue
. Queue is an object that for we to let tasks to run sync or async.
DispatchQueue
Before knowing what is sync and async, I have to introduce a concept calls Dispatch Queue
, which is called as Queue before, first we should import Foundation
, and initialize a queue waiting for task.
1 | let queue = DispatchQueue(label: "zrzz.site") |
This is a customed queue that runs tasks serialy, we can give .concurrent to the ATTRIBUTE “attributes” to make it run tasks concurrently. Like this.
1 | let queue = DispatchQueue(label: "zrzz.site", attributes: .concurrent) |
The basic method of initialize DispatchQueue
has one parameter, label is decided by you, as long as it is unique.
global and main
1 | DispatchQueue.global()/DispatchQueue.main |
global queue can runs tasks concurrently
main queue is relative to main thread whick controls our UI update, also it is serial.
Sync Async
Sync
and Async
, as its literal meaning, we can make our queue run two tasks synchronously or asynchronously. To realize it better, plz run codes below and observe results.
1 | import Foundation |
We create one queue, let it syncly run a for loop, and let main thread (outside the closure) use sync method, and Cpu exec our tasks by order.
We can see the queue doesn’t create new thread to handle tasks, but still let them runs in the main thread.
What if we use async method? Let’s check.
1 | import Foundation |
As expected, two tasks run asyncly, tasks in the clousure runs in a new thread.
So let’s conclude async and sync with serial and concurrent queue.
sync + serial
won’t create new thread, runs in order.
async + serial
create new thread, runs in order.
sync + concurrent
won’t create new thread, runs in order
async + concurrent
create new thread every time (useless thread will be recycled, don’t worry about it), runs randomly.
Addition
however, you CAN’T use sync in main Queue, because main Queue is used for UI update, and the action SYNC will block the thread, which is not allowed in Main Thread.
if you use async + mainQueue, it won’t create thread and runs in order. And there is a interesting action if you run the code below.
1 | import Foundation |
you can see the tasks not runs as expected. I think the reason is that tasks in async closure was added to the end of queue.
Barrier
if we want some tasks run first and other behind them, we can use barrier. Like this.
1 | import Foundation |
Quality of Service (QoS)
However, we usually want to do things concurrently, and we can create different queues for them. And use qos to control priority.
DispatchQos is ordered by below.
- userInteractive
- userInitiated
- default
- utility
- background
- unspecified
1 | import Foundation |
we can see tasks in queue2 always behind that in queue1.
DispatchGroup
Group can be regarded as an tasks set. It’s normol usage is to know when the tasks were done.
1 | import Foundation |
or you can manually control tasks
1 | import Foundation |
Semaphore
use semaphore to limit the count of tasks that running at the same time.
1 | import Foundation |