We are going to take a look at threading and Grand Central Dispatch in Swift, we will explore what threads and queues are as well as the Grand Central Dispatch or GCD APIs is to manage your queues in the process, it will also touch on synchronous vs. asynchronous. Finish with an overview of the code and dispatch groups but this is something you want to learn in this tutorial.
What is Concurrency/Multithreading?:
We can optimize the performance of an app in
You will need to know concurrency to make your app more responsive and fast.
Concurrency is a condition in a program where more than one task is happening at the same time then it’s called concurrency.iOS 4 supports multiple tasks to execute at the same time. We will run multiple tasks at an equivalent time by adding some code. So you'll run tasks within the background (like downloading or processing data) while you retain your interface responsively.
- Using Grand Central Dispatch(GCD)
- Using Operations and OperationQueues
GCD (Grand Central Dispatch):
The Grand Central Dispatch was first introduced in iOS 4, and it
- It improves application performance and responsiveness.
- The app will become more smooth.
- Execute multiple tasks at a time or one by one as per your requirements.
Thread:
Main Thread:
In iOS, there is a concept of the Main Thread or UI Thread. That thread becomes user interaction as a user button click.The main thread is responsible for keeping the UI running smoothly and responding to user input. It can only execute one task at a time.
If
-Keep the UI thread free, to keep your app responsive
Background Thread:
All iOS apps use the main thread to handle UI operations. Calling long-running operations from this main thread can lead
Therefore, time-consuming processes should be done in a separate thread say a “Background thread” to free up the main UI thread so that the app remains responsive. If heavy operations like network calls, database access, and image downloading are performed on a background thread.
Queues:
Queues are just a bunch of code blocks lined up or queued up waiting for a thread to execute them. you don't need to worry about threads in Swift only Queues the system takes care of providing and allocating threads to execute the code of the Queue.Queues are data structures that manage objects
Dispatch Queues:
A dispatch queue is an object-like structure that manages the tasks you submit to it. All dispatch queues are first-in, first-out data structures. Thus, the tasks you add to a queue are always started in the same order that they were added.
Dispatch queues are thread-safe
Different Types of Dispatch Queues:
Main Queue:
How about the main thread?:
The main dispatch queue is a globally available serial queue executing tasks on the application’s main thread. As the main thread is used for UI updates it’s important to be conscious when executing tasks on this queue. Therefore, it’s valuable to use the earlier described dispatch APIs to perform tasks on a different thread.
You can start doing the heavy lifting on a background queue and dispatch back to the main queue when you’re done.
let concurrentQueue = DispatchQueue(label: "appcodezip.concurrent.queue", attributes: .concurrent)
concurrentQueue.async {
// Perform the data request and JSON decoding on the background queue.
fetchData()
DispatchQueue.main.async {
/// Access and reload the UI back on the main queue.
tableView.reloadData()
}
}
Serial Queues:
Serial queues execute one task at a time and
Serial queues guarantee that
Concurrent queues:
Concurrent queues allow multiple tasks to run at
Concurrent Dispatch Queue A concurrent dispatch queue runs as many tasks as it can without waiting for the started tasks to finish.
Serial vs Concurrent Dispatch Queues with an example:
func serialQueues () {
let serialQueue = DispatchQueue(label: "appcodezip.com") //default queue type is a serial queue
let startDate = Date ()
for i in 0...4 {
serialQueue.async { //run tasks on a background thread
sleep(2) //do some task as webservice or database
let timeTaken = Date().timeIntervalSince(startDate)
print("serial Queue task \(i) done! total time taken: \(timeTaken)")
}
}
}
Program Execution-serial Queue task 0 done! total time taken: 2.0022469758987427
serial Queue task 1 done! total time taken: 4.005535006523132
serial Queue task 2 done! total time taken: 6.005913019180298
serial Queue task 3 done! total time taken: 8.007167935371399
serial Queue task 4 done! total time taken: 10.011394023895264
Example with concurrent Queue -func concurrentQueues () {
let concurrentQueue = DispatchQueue(label: "appcodezip.com", attributes: .concurrent)
let startDate = Date ()
for i in 0...4 {
concurrentQueue.async {
sleep(2) //do some task as webservice or database
let timeTaken = Date().timeIntervalSince(startDate)
print("concurrent Queue task \(i) done! total time taken: \(timeTaken)")
}
}
}
Program Execution-concurrent Queue task 2 done! total time taken: 2.001850962638855
concurrent Queue task 3 done! total time taken: 2.0018709897994995
concurrent Queue task 1 done! total time taken: 2.0017420053482056
concurrent Queue task 4 done! total time taken: 2.0018869638442993
concurrent Queue task 0 done! total time taken: 2.0017420053482056
As we will see from the examples above, a serial queue will complete each task within the order they're submitted to the queue. Each task will await the previous task to end before executing. As for the concurrent queue, each task doesn't serve the others within the queue and executes as soon as possible; the advantage is that each task on the queue will run at an equivalent time on separate threads, making a concurrent queue take less time than a serial queue. If the order of execution of tasks isn't important, always use a concurrent queue for the simplest efficiency.
user-initiated tasks are second priority after the user-interactive. user-interactive tasks in their priority on the system you assign this class to tasks that provide immediate results for something the user is doing or that would prevent the user from using your app, for example, you might use this quality of service class to load the content of an email that you want to display to the user.
The next two types are lower in priority for execution.
.utility:
Utility tasks have a lower priority than user initiated and user interactive tasks but a higher priority event background tasks you assign this quality of service class to tasks that do not permit the user from continuing to use your app. for example you might assign this class to long running tasks whose progress the user doesn't have to follow actively.
.background:
Background tasks have the lowest priority of all tasks you assign this class to tasks or dispatched queues that you use to perform work while your app is running in the background like maintenance tasks or cleanup.
It will be say assigned the default case The default task has a lower priority than user-interactive and user-initiated. Assign this class to the task that your app initiates or performs active work on the user’s behalf.
// User-interactive
DispatchQueue.global(qos: .userInteractive).async {
// Event handling task & Animation task
// Task compete then update UI (in main queue)
}
// User-initiated:
DispatchQueue.global(qos: .userInitiated).async {
// Load conent of email, etc
}
// Defaul
DispatchQueue.global(qos: .default).async {
// task that your app initiates
// performs active work on the user's behalf
}
// Utility
DispatchQueue.global(qos: .utility).async {
//Low priority task
}
// Background
DispatchQueue.global(qos: .background).async {
// task which needs to be executed when the app is running in the background
}
DispatchQueue.main.sync{
//code to be execute
}
DispatchQueue.global().async{
//code to be execute
}
Thanks for reading!!
0 Comments