一个常见的场景就是在一个全局队列进行一些操作后切换到主线程配置UI。现在是这么写:
DispatchQueue.global().async {
// code
DispatchQueue.main.async {
// 主线程中
}
}
概念:
串行 VS 并发
串行与并发用来表述队列里面的任务执行的顺序。 串行(serial) 在同一时间点总是单独执行一个任务,并发(concurrent)则可以同时执行多个任务。
任务
任务可以看成是一段未被执行的代码块, 一个方法可以是一个一个任务, 一写代码的集合可以看做是一个任务, 在GCD中, 队列里面的任务就是未被执行的一块闭包
同步 VS 异步
同步和异步表述的是函数何时将控制权返回给调用者,以及在返回时任务的完成情况。
同步(任务一个一个执行)函数只有在任务完成后才会返回。
异步(任务可以并发执行)函数会立即返回,不会等待任务完成。因此异步函数不会阻塞当前线程。
主队列
系统提供了一种特殊的顺序队列 main queue。和其他的顺序队列一样,在这个队列里的任务同一时刻只有一个在执行。然而,这个队列保证了所有任务会在主线程中执行,主线程是唯一一个允许更新UI的线程。这个队列用来向 UIView 对象发消息或发通知。
队列优先级
原先的GCD只有四个优先级,high,default,low,background
然而现在的GCD有六个优先级,background,utility,default,userInitiated,userInteractive,unspecified
这些优先级有结构体DispatchQoS来管理
串行队列
//创建的队列默认是串行的, 队列里的任务是以此按照添加的顺序来执行的(FIFO)
//第一个for循环结束之后才会执行下一个for循环
func serialQueues() {
let queue = DispatchQueue(label: "com.jason")
//创建一个含有优先级的串行队列
//let anotherQueue = DispatchQueue(label:"com.appcoda.anotherQueue", qos:.utility)
queue.async {
for i in 1..<10 {
print("🍠" + String(i))
}
}
queue.async {
for i in 1..<10 {
print("🍋" + String(i))
}
}
}
并行队列
func concurrentQueues() {
//并行队列, 队列里面的任务并发执行
/**
label: 队列的唯一标识符
qos: 优先级
attributes: 队列类型
*/
let anotherQueue = DispatchQueue(label:"com.appcoda.anotherQueue", qos:.utility, attributes:.concurrent)
anotherQueue.async {
for i in 1..<10 {
print("🍠" + String(i))
}
}
anotherQueue.async {
for i in 1..<10 {
print("🍋" + String(i))
}
}
}
初始化不活跃的串行队列
var inactiveQueue: DispatchQueue!
func concurrentQueues() {
//串行队列, 初始不活跃, 需要时才执行
let anotherQueue = DispatchQueue(label:"com.appcoda.anotherQueue", qos:.utility, attributes:.initiallyInactive)
inactiveQueue = anotherQueue
anotherQueue.async {
for i in 1..<10 {
print("🍠" + String(i))
}
}
anotherQueue.async {
for i in 1..<10 {
print("🍋" + String(i))
}
}
}
调用
concurrentQueues()
if let queue = inactiveQueue {
queue.activate()
}
初始化不活跃的并行队列
//并行队列, 初始不活跃
let anotherQueue = DispatchQueue(label:"com.appcoda.anotherQueue", qos:.utility, attributes:[.initiallyInactive, .concurrent])
延迟执行
func queueWithDelay() {
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
print("延迟5秒执行")
}
}
DispatchWorkItem
DispatchWorkItem是一个代码块,它可以被分到任何的队列,包含的代码可以在后台或主线程中被执行,简单来说:它被用于替换我们前面写的闭包
func useWorkItem() {
var value = 10
//创建一个workItem
let workItem = DispatchWorkItem {
value += 5
}
//激活workItem
workItem.perform()
//获取全局一个队列
let queue = DispatchQueue.global()
//在队列里面执行workItem
queue.async(execute: workItem)
//workItem被执行完成后收到的通知
workItem.notify(queue: DispatchQueue.main) {
print(value)
}
}
DispatchGroup(任务组)
如果想在dispatch_queue中所有的任务执行完成后再做某种操作可以使用DispatchGroup。原先的dispatch_group_t由现在的DispatchGroup对象代替。
let group = DispatchGroup()
let queueBook = DispatchQueue(label: "book")
queueBook.async(group: group) {
// 下载图书
}
let queueVideo = DispatchQueue(label: "video")
queueVideo.async(group: group) {
// 下载视频
}
group.notify(queue: DispatchQueue.main) {
// 下载完成
}
DispatchGroup会在组里的操作都完成后执行notify。
单例
//final关键字的作用是这个类或方法不希望被继承和重写
final class Single: NSObject {
static let shared = Single()
//这里的所有单例init方法一定要定义成private的,不然外部依然可以使用init方法初始化变量。
private override init() {}
}
//静态变量进行创建
final class Singleton {
static private let staticInstance: Singleton = Singleton()
static func sharedInstance() -> Singleton {
return staticInstance
}
private init() {}
}