之前对GCD的理解很浅,就是那种看了一会能勉强理解,可是过一段时间又给忘记了,又得回头来看。这次下定决心一定要把GCD给吃透了。网上也有很多不错关于GCD的文章帮助了我的理解。
很多情况下,我们使用GCD的情况基本是以下几种:
- 异步获取网络数据,在主线程中刷新UI
override func viewDidLoad() {
super.viewDidLoad()
loadData { (result) in
// 获取到数据赋值
self.dataArr = result
//刷新tableView列表
self.tableView.reloadData()
}
setupUI()
}
func loadData(completion:@escaping (_ result:([String]))->()){
DispatchQueue.global().async {
print("模拟网络延迟")
Thread.sleep(forTimeInterval: 3.0)
let arr = ["😝","🤣","🙄","🌹","💰","😪","😴"]
DispatchQueue.main.async {
print("回到主线程,更新UI")
completion(arr)
}
}
}
- 定时操作
func timer() {
print("开始")
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2.0) {
print("结束")
}
}
- 设计单例
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
});
但往往形成了这种固有的套路以后,自己代码写着写着的时候回头看就很容易产生疑问,为什么要这样写?到底什么是队列?什么是任务?
任务:就是执行操作的意思,换句话说就是你在线程中执行的那段代码。而GCD中的任务只是一个代码块,它可以指一个block或者函数指针。执行任务有两种方式:同步执行(sync)和异步执行(async)。两者的主要区别是:是否等待队列的任务执行结束,以及是否具备开启新线程的能力。
-
同步执行(sync):
同步添加任务到指定的队列中,在添加的任务执行结束之前,会一直等待,直到队列里面的任务完成之后再继续执行。
只能在当前线程中执行任务,不具备开启新线程的能力。 -
异步执行(async):
异步添加任务到指定的队列中,它不会做任何等待,可以继续执行任务。
可以在新的线程中执行任务,具备开启新线程的能力。
队列(Dispatch Queue):这里的队列指执行任务的等待队列,即用来存放任务的队列。队列是一种特殊的线性表,采用 FIFO(先进先出)的原则,即新任务总是被插入到队列的末尾,而读取任务的时候总是从队列的头部开始读取。每读取一个任务,则从队列中释放一个任务。在 GCD 中有两种队列:串行队列和并发队列。两者都符合 FIFO(先进先出)的原则。两者的主要区别是:执行顺序不同,以及开启线程数不同。
-
串行队列(Serial Dispatch Queue):
每次只有一个任务被执行。让任务一个接着一个地执行。(只开启一个线程,一个任务执行完毕后,再执行下一个任务)
-
并发队列(Concurrent Dispatch Queue):
可以让多个任务并发(同时)执行。(可以开启多个线程,并且同时执行任务)
这以上对任务和队列的理解是源自这两篇很好的文章:
巧谈GCD
iOS多线程:『GCD』详尽总结
有了上面大神们对队列和任务的解释,现在对GCD也有了些许概念。在这个基础上,我来说说我的一个技巧理解GCD的方式。首先我们可以把任务看做是水滴,而队列就是管道了。串行队列的管道很细,只有容纳下一滴水的直径。而并发队列的管道的直径很粗,可以容纳下很多水滴。下面就具体到队列与任务之间的搭配了。
-
同步+串行
不会开启新线程,在当前线程执行任务。任务是串行的,执行完一个任务,再执行下一个任务。任务1,任务2依次执行
同步+串行
-
同步+并发
在当前线程中执行任务,不会开启新线程,执行完一个任务,再执行下一个任务。因为是同步的任务,所以会等待任务1执行完,在执行任务2。同理,任务3也是等任务2执行完毕之后再开始执行
同步+并发
同步任务是没有开辟线程的能力的
-
异步+串行
会开启新线程,但是因为任务是串行的,执行完一个任务,再执行下一个任务
异步+串行 -
异步+并发
可以开启多个线程,任务交替(同时)执行。会并行执行多个任务,这也是我们最常用的一种方式。 异步+并发
异步任务是有开辟线程的能力的,但是在主队列中,异步就失去了这种能力
-
同步+主队列
在不同线程中调用结果也是不一样,在主线程中调用会出现死锁,而在其他线程中则不会。 -
异步+主队列
只在主线程中执行任务,执行完一个任务,再执行下一个任务。
队列和任务组合的总结
另外在github上有OC版的demo,如有什么问题,欢迎大家补充
OC Demo
网友评论