iOS Dispatch swift GCD
iOS
GCD
Dispatch
swift
Framework Dispatch
Execute code concurrently on multicore hardware by submitting work to dispatch queues managed by the system.
import Dispatch.base
import Dispatch.block
import Dispatch.data
import Dispatch.group
import Dispatch.io
import Dispatch.object
import Dispatch.once
import Dispatch.queue
import Dispatch.semaphore
import Dispatch.source
import Dispatch.time
import Dispatch
import os_object
父类 | 2 | 3 | 4 |
---|---|---|---|
NSObject | OS_object | DispatchObject | DispatchQueue |
DispatchGroup | |||
DispatchSource | |||
DispatchWorkItem |
// 在 swift3.0 中新加的, OS_object 继承自 NSObject
// 在 GCD 中所有的对象都间接的继承自 NSObject。
import os_object
open class OS_object : NSObject {
}
1.DispatchQueue
class DispatchQueue: DispatchObject
⭑⭑⭑⭑ Important
Attempting to synchronously execute a work item on the main queue results in deadlock.
主线程同步派发一个block任务产生死锁的问题
主队列是串行队列,执行同步派发(dispatch_sync)时将等待其派发的block任务执行完毕后再返回,即不是立即返回,阻塞在此。 而block任务由于处在串行队列中,需要等前面派发的代码执行完毕才能执行,形成死锁
- 判断会不会产生死锁, 主要看是不是当前在不在主线程, 新加入的主线程任务是同步还是异步的!
并发队列 | 串行队列(非主队列) | 主队列(只有主线程,串行队列) | |
---|---|---|---|
同步 | 不开启新的线程,串行 | 不开启新的线程,串行 | 不开启新的线程,串行 |
异步 | 开启新的线程,并发 | 开启新的线程,串行 | 不开启新的线程,串行 |
队列决定了是并行还是串行,同步异步决定了是否开启新的线程:
即便你是串行队列,但是是异步执行,所以会启用新的线程。
1.1 Creating a Dispatch Queue 初始化
- 获取主线程队列
class var main: DispatchQueue
//The dispatch queue associated with the main thread of the current process.
- 获取全局队列
class func global(qos: DispatchQoS.QoSClass) -> DispatchQueue
// Returns the global system queue with the specified quality-of-service class.
- 自定义队列
init(label: String, qos: DispatchQoS, attributes: DispatchQueue.Attributes, autoreleaseFrequency: DispatchQueue.AutoreleaseFrequency, target: DispatchQueue?)
//Creates a new dispatch queue to which you can submit blocks.
In swift, there is not.serial
attribute anymore, but dispatch queues are by default serial, unless you specify the .concurrent attribute:
//串行对列
let serialQueue = DispatchQueue(label: "label")
//并发对列
let concurrentQueue = DispatchQueue(label: "label", attributes: .concurrent)
- 新增方法(以后补充)
class OS_dispatch_queue_main
//A system-provided dispatch queue that schedules tasks for serial execution on the app's main thread.
class OS_dispatch_queue_global
//A system-provided dispatch queue that schedules tasks for concurrent execution.
class OS_dispatch_queue_serial
//A custom dispatch queue that schedules tasks for serial execution on an arbitrary thread.
class OS_dispatch_queue_concurrent
//A custom dispatch queue that schedules tasks for concurrent execution.
1.2 Executing Tasks Asynchronously 执行异步任务
func async(execute: DispatchWorkItem)
//Schedules a work item for immediate execution, and returns immediately.
func asyncAfter(deadline: DispatchTime, execute: DispatchWorkItem)
///Schedules a work item for execution at the specified time, and returns immediately.
func asyncAfter(deadline: DispatchTime, qos: DispatchQoS, flags: DispatchWorkItemFlags, execute: () -> Void)
//Schedules a block for execution using the specified attributes, and returns immediately.
func asyncAfter(wallDeadline: DispatchWallTime, execute: DispatchWorkItem)
//Schedules a work item for execution after the specified time, and returns immediately.
func asyncAfter(wallDeadline: DispatchWallTime, qos: DispatchQoS, flags: DispatchWorkItemFlags, execute: () -> Void)
//Schedules a block for execution using the specified attributes, and returns immediately.
1.3 Executing Tasks Synchronously执行同步任务
func sync(execute: DispatchWorkItem)
//Submits a work item for execution on the current queue and returns after that block finishes executing.
func sync(execute: () -> Void)
//Submits a block object for execution and returns after that block finishes executing.
func sync<T>(execute: () -> T) -> T
//Submits a work item for execution and returns the results from that item after it finishes executing.
func sync<T>(flags: DispatchWorkItemFlags, execute: () -> T) -> T
//Submits a work item for execution using the specified attributes and returns the results from that item after it finishes executing.
1.4 Executing a Task in Parallel 并行执行任务
class func concurrentPerform(iterations: Int, execute: (Int) -> Void)
//Submits a single block to the dispatch queue and causes the block to be executed the specified number of times.
1.5 Dispatching Work to Groups 隐式往Group中添加任务 (同2.5)
func async(group: DispatchGroup, execute: DispatchWorkItem)
//Schedules a work item asynchronously for execution and associates it with the specified dispatch group.
func async(group: DispatchGroup?, qos: DispatchQoS, flags: DispatchWorkItemFlags, execute: () -> Void)
//Schedules a block asynchronously for execution and optionally associates it with a dispatch group.
1.6 Managing Queue Attributes 管理队列属性
var label: String
/he label you assigned to the dispatch queue at creation time.
var qos: DispatchQoS
//The quality-of-service level assgined to the queue.
func setTarget(queue: DispatchQueue?)
//Specifies the dispatch queue on which to perform work associated with the current object.
func setTarget(queue: DispatchQueue?)
需要避免循环设置;queue = Nil时, the system will provide a queue that is appropriate for the current object.
⭑⭑⭑⭑ Important
When setting up target queues, it is a programmer error to create cycles in the dispatch queue hierarchy. In other words, don't set the target of queue A to queue B and set the target of queue B to queue A.
1.7 Getting and Setting Contextual Data (待完善)
1.8 Managing the Main Dispatch Queue
func dispatchMain() -> Never
//Executes blocks submitted to the main queue.
/*
This function "parks" the main thread and waits for blocks to be submitted to the main queue.
Applications that call UIApplicationMain(_:_:_:_:) (iOS), NSApplicationMain(_:_:) (macOS),
or CFRunLoopRun() on the main thread must not call dispatchMain().
*/
1.9 Scheduling Combine Publishers (待完善)
2.DispatchGroup
class DispatchGroup: DispatchObject
ref: https://developer.apple.com/documentation/dispatch/dispatchgroup
DispatchGroup
允许您聚合一组任务并同步组上的行为。 可以将多个工作项附加到组,并安排它们在同一队列或不同队列上进行异步执行。 当所有工作项完成执行时,该组将执行其完成处理程序。 您还可以同步等待组中的所有任务完成执行。
2.1 初始化 init
2.2 Completion Handler
func notify(qos: DispatchQoS, flags: DispatchWorkItemFlags, queue: DispatchQueue, execute: () -> Void)
//Schedules the submission of a block with the specified attributes to a queue when all tasks in the current group have finished executing.
func notify(queue: DispatchQueue, work: DispatchWorkItem)
//Schedules the submission of a block to a queue when all tasks in the current group have finished executing.
2.3 Waiting for Tasks to Finish Executing
func wait()
//Waits synchronously for the previously submitted work to finish.
func wait(timeout: DispatchTime) -> DispatchTimeoutResult
//Waits synchronously for the previously submitted work to complete, and returns if the work is not completed before the specified timeout period has elapsed.
func wait(wallTimeout: DispatchWallTime) -> DispatchTimeoutResult
//Waits synchronously for the previously submitted work to complete, and returns if the work is not completed before the specified timeout period has elapsed.
2.4 显示地往Group中添加任务, 修改group中任务计数
* Updating the Group Manually 手动更新group
- 入组
enter
、 出组leave
必须成对出现 - 如果调度组 group 中没有任务,会直接执行
notify
方法 -
leave
的次数enter
的次数, 回崩溃
func enter()
//Explicitly indicates that a block has entered the group.
//
func leave()
//Explicitly indicates that a block in the group finished executing.
2.5 隐式往Group中添加任务
* Dispatching Work to Groups
DispatchQueue 's methods
func async(group: DispatchGroup, execute: DispatchWorkItem)
//Schedules a work item asynchronously for execution and associates it with the specified dispatch group.
func async(group: DispatchGroup?, qos: DispatchQoS, flags: DispatchWorkItemFlags, execute: () -> Void)
//Schedules a block asynchronously for execution and optionally associates it with a dispatch group.
3.DispatchWorkItem
The work you want to perform, encapsulated in a way that lets you attach a completion handle or execution dependencies.
A DispatchWorkItem encapsulates work to be performed on a dispatch queue or within a dispatch group. You can also use a work item as a DispatchSource
event, registration, or cancellation handler.
class DispatchWorkItem
3.1 Creating a Work Item 初始化
init(qos: DispatchQoS, flags: DispatchWorkItemFlags, block: () -> Void)
//Creates a new dispatch work item from an existing block and assigns it the specified quality-of-service class.
struct DispatchWorkItemFlags
//A set of behaviors for a work item, such as its quality-of-service class and whether to create a barrier or spawn a new detached thread.
static let assignCurrentContext: DispatchWorkItemFlags
static let barrier: DispatchWorkItemFlags //标记为栅栏任务, 等待前面的异步任务都完成, 再执行栅栏任务
static let detached: DispatchWorkItemFlags
static let enforceQoS: DispatchWorkItemFlags
static let inheritQoS: DispatchWorkItemFlags
static let noQoS: DispatchWorkItemFlags
3.2 Executing the Work Item 执行一个workitem
func perform()
//Executes the work item's block synchronously on the current thread.
3.3 Adding a Completion Handle 添加一个完成回调
func notify(queue: DispatchQueue, execute: DispatchWorkItem)
//Schedules the execution of the specified work item after the completion of the current work item.
func notify(qos: DispatchQoS, flags: DispatchWorkItemFlags, queue: DispatchQueue, execute: () -> Void)
//Schedules the execution of the specified work item, with the specified quality-of-service, after the completion of the current work item.
3.4 Waiting for the Completion of a Work Item 等待任务完成
func wait()
//Causes the caller to wait synchronously until the dispatch work item finishes executing.
func wait(timeout: DispatchTime) -> DispatchTimeoutResult
//Causes the caller to wait synchronously until the dispatch work item finishes executing, or until the specified time elapses.
func wait(wallTimeout: DispatchWallTime) -> DispatchTimeoutResult
//Causes the caller to wait synchronously until the dispatch work item finishes executing, or until the specified time elapses.
struct DispatchTime
//A point in time relative to the default clock, with nanosecond precision.
struct DispatchWallTime
//An absolute point in time according to the wall clock, with microsecond precision.
3.5 Canceling a Work Item 取消执行m
func cancel()
//Cancels the current work item asynchronously.
var isCancelled: Bool
//A Boolean value indicating whether the work item has been canceled.
DEMO
1.栅栏线程实现
//定义
lazy var queue: DispatchQueue = {
//自定义一个串行队列
//let d = DispatchQueue.init(label: "serial")
//自定义一个并发队列, 附加到全局队列中
let d = DispatchQueue(label: "concurrent", qos: DispatchQoS.default, attributes: DispatchQueue.Attributes.concurrent, target: DispatchQueue.global())
return d
}()
private var group = DispatchGroup()
//按钮点击事件
func clickBtn(_ sender: UIButton) {
queue.async(group: group) {
Thread.sleep(forTimeInterval: 5)
print("\(Date())~~ \(Thread.current)--- \(Thread.current.isMainThread) ~~~ [ sleep \(4) ]")
}
queue.async(group: group) {
Thread.sleep(forTimeInterval: 4)
print("\(Date())~~ \(Thread.current)--- \(Thread.current.isMainThread) ~~~ [ sleep \(3) ]")
}
self.queue.async(group: self.group, qos: DispatchQoS.default, flags: DispatchWorkItemFlags.barrier, execute: {
print("\(Date())~~ \(Thread.current)--- \(Thread.current.isMainThread) ~~~ [ sleep \(0) ]")
})
queue.async(group: group) {
Thread.sleep(forTimeInterval: 2)
print("\(Date())~~ \(Thread.current)--- \(Thread.current.isMainThread) ~~~ [ sleep \(2) ]")
}
group.notify(queue: DispatchQueue.main) {
print("\(Date()) 所有任务完成 \(Thread.current)--- \(Thread.current.isMainThread) ~~~ [ \(999) ]")
}
}
//打印结构
/*
2019-06-18 07:21:54 +0000~~ <NSThread: 0x600000ee40c0>{number = 5, name = (null)}--- false ~~~ [ sleep 3 ]
2019-06-18 07:21:55 +0000~~ <NSThread: 0x600000ee4540>{number = 6, name = (null)}--- false ~~~ [ sleep 4 ]
2019-06-18 07:21:55 +0000~~ <NSThread: 0x600000ee4540>{number = 6, name = (null)}--- false ~~~ [ sleep0 ]
2019-06-18 07:21:57 +0000~~ <NSThread: 0x600000ee4540>{number = 6, name = (null)}--- false ~~~ [ sleep 3 ]
2019-06-18 07:21:57 +0000 所有任务完成 <NSThread: 0x600000e92980>{number = 1, name = main}--- true ~~~ [ 999 ]
*/