GCD I
Executing tasks in parallel.
GCD I
Executing tasks in parallel.
0
0
Checkbox to mark video as read
Mark as read

In Swift, a thread refers to a single sequence of execution within a program. By default, code runs on the main thread, which handles tasks sequentially, one after another. This thread is especially important for UI updates.

To prevent the main thread from becoming unresponsive (e.g., when performing long tasks like data fetching), Swift uses concurrency with multiple threads. Apple provides Grand Central Dispatch (GCD), allowing developers to run tasks in parallel on different threads using queues, ensuring smoother app performance without freezing the UI.

There are 3 types of queues that execute with different priorities:

  • Main Queue
  • Global Queue
  • Custom Queue

Main Queue

The Main Queue has the highest priority and is where we should run UI-related operations to avoid crashes. This is used by default, but if we use another queue, we should execute UI-related changes on the Main Queue like this:

DispatchQueue.main.async {
    myLabel.text = "Hello"
}

Global Queue

The Global Queue is divided into four types (plus the default type) that define the Quality of Service (QoS), giving the queue different priority levels. Here are the types, listed from highest to lowest priority, along with their usage:

  • userInteractive: for instant executions.
  • userInitiated: for near-instant executions, lasting a few seconds.
  • default: we avoid using this type as the system will infer it automatically.
  • utility: for tasks taking a few seconds to a few minutes.
  • background: for long tasks, taking minutes or even hours.

Here's an example where we run a long for loop that takes 2 to 3 seconds to complete. We execute this in a queue of type .userInitiated, and when it's done, we print a message using the Main Queue, though this last step isn't strictly necessary for print().

DispatchQueue.global(qos: .userInitiated).async {
    print("START QUEUE: \(Date())")
    
    var cont: Double = 0
    for _ in 0..<100000 {
        cont += 1
    }

    DispatchQueue.main.async {
        print("MAIN QUEUE: \(Date())")
    }
}

print("START MAIN: \(Date())")

// Console output:
// START QUEUE: 2021-02-09 13:38:22 +0000
// START MAIN: 2021-02-09 13:38:22 +0000
// MAIN QUEUE: 2021-02-09 13:38:24 +0000

Custom Queue

It's also possible to create custom queues where we can use parameters like label, allowing us to identify a queue when it's running. Otherwise, it works the same as other queues.

let queue = DispatchQueue(label: "My Queue", qos: .userInitiated, attributes: .concurrent)

queue.async {
    guard let queueName = String(validatingUTF8: __dispatch_queue_get_label(nil)) else { return }
    print("START \(queueName): \(Date())")

    var cont: Double = 0
    for _ in 0..<100000 {
        cont += 1
    }

    print("FINISH \(queueName): \(Date())")
}

print("START MAIN: \(Date())")

// Console output:
// START MAIN: 2021-02-09 13:58:09 +0000
// START My Queue: 2021-02-09 13:58:09 +0000
// FINISH My Queue: 2021-02-09 13:58:12 +0000

0 Comments

Join the community to comment

Be the first to comment

Accept Cookies

We use cookies to collect and analyze information on site performance and usage, in order to provide you with better service.

Check our Privacy Policy