Swift Language Concurrency Obtaining a Grand Central Dispatch (GCD) queue


Grand Central Dispatch works on the concept of "Dispatch Queues". A dispatch queue executes tasks you designate in the order which they are passed. There are three types of dispatch queues:

  • Serial Dispatch Queues (aka private dispatch queues) execute one task at a time, in order. They are frequently used to synchronize access to a resource.
  • Concurrent Dispatch Queues (aka global dispatch queues) execute one or more tasks concurrently.
  • The Main Dispatch Queue executes tasks on the main thread.

To access the main queue:

let mainQueue = DispatchQueue.main
let mainQueue = dispatch_get_main_queue()

The system provides concurrent global dispatch queues (global to your application), with varying priorities. You can access these queues using the DispatchQueue class in Swift 3:

let globalConcurrentQueue = DispatchQueue.global(qos: .default)

equivalent to

let globalConcurrentQueue = DispatchQueue.global()
let globalConcurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

In iOS 8 or later, the possible quality of service values which may be passed are .userInteractive, .userInitiated, .default, .utility, and .background. These replace the DISPATCH_QUEUE_PRIORITY_ constants.

You can also create your own queues with varying priorities:

let myConcurrentQueue = DispatchQueue(label: "my-concurrent-queue", qos: .userInitiated, attributes: [.concurrent], autoreleaseFrequency: .workItem, target: nil)
let mySerialQueue = DispatchQueue(label: "my-serial-queue", qos: .background, attributes: [], autoreleaseFrequency: .workItem, target: nil)
let myConcurrentQueue = dispatch_queue_create("my-concurrent-queue", DISPATCH_QUEUE_CONCURRENT)
let mySerialQueue = dispatch_queue_create("my-serial-queue", DISPATCH_QUEUE_SERIAL)

In Swift 3, queues created with this initializer are serial by default, and passing .workItem for autorelease frequency ensures an autorelease pool is created and drained for each work item. There is also .never, which means you will be managing your own autorelease pools yourself, or .inherit which inherits the setting from the environment. In most cases you probably won't use .never except in cases of extreme customization.