GCD中有一个重要的概念,派发队列(dispatch queue)。派发队列是一个对象,它可以接受任务,并将任务以先到先执行的顺序来执行。派发队列可以是并发的或串行的。并发队列可以执行多任务,串行队列同一时间只能执行单一任务。
1、3中类型的派发队列
(1)串行队列,串行队列通常用于同步访问一个特定的资源,每次只能执行一个任务。使用函数dispatch_queue_create,可以黄建串行队列。
(2)并发队列,也称为全局派发队列,可以并发地执行一个或多个任务。当并发地执行多个任务时,必然涉及哪些任务先执行,哪些任务后执行的问题。在macOS 10.10和iOS8之前,是通过并发队列优先级决定的,之后是通过QoS(Quality of Service)技术管理。使用dispatch_get_global_queue函数,可以创建并发队列。
(3)主队列,它在应用程序的主线程中,用于更新UI。其他两个队列不能更新UI。使用dispatch_get_main_queue函数,可以获得主队列。
2、QoS技术
QoS技术是在macOS10.10和iOS8之后的新技术,通过QoS高速操作系统并发队列如何工作,然后操作系统会通过合理的资源控制,从而以最搞笑的方式执行并发队列。这其中主要涉及CPU调度、IO操作优先级、任务执行在哪个线程以及执行的顺序等内容。我们通过抽象的Quality of Service参数来表明任务的意图以及类别。QoS提供NSQualityOfService(swift是QualityOfService)枚举类型,有如下5个成员:
(1)NSQualityOfSErviceUserInteractive,与用户交互的任务,这些任务通常跟UI刷新相关,例如动画,他会在一瞬间完成。
(2)NSQualityOfServiceUserInitiated,由用户发起的并且可以立即得到结果的任务。例如翻动表视图时加载数据,然后显示单元格,这些任务通常跟后续的用户交互相关,会在几秒或者更短的时间内完成。
(3)NSQualityOfServiceUtility,一些耗时的任务,这些任务不会马上返回结果,例如下载任务,它可能花费好几秒或者几分钟的时间。
(4)NSQualityOfServiceBackground,这些任务对用户不可见,可以长时间在后台运行。
(5)NSQualityOfServiceDefault,优先级介于NSQualityOfSErviceUserInteractive和NSQualityOfServiceUtility之间,这个值是系统默认值,我们不应该使用它设置自己的任务。
例:从网上加载一张图片
Swift代码
// A code block
@IBAction func click(_ sender:AnyObject){
self.imageVeiw.image=nil
let url=URL(string:"http://www.a.com/img/test.jpg")
DispatchQueue.global(qos:.utility).async{
let imgData=try?Data(contentsOf:url!)
let img=UIImage(data:imgData!)
DispatchQueue.main.async{
self.imageVeiw.image=img
}
}
}
ObjectiveC代码
// A code block
-(IBAction)click:(id)sender{
self.imageVeiw.image=nil;
NSURL *url=[NSURL URLWithString:@"http://www.a.com/img/test.jpg"];
//创建全局派发队列,由于我们是要从网络下载图片,需要将并发队列设置为NSQualityOfServiceUtility。
dispatch_async(dispatch_get_global_queue(NSQualityOfServiceUtility,0),^{
NSData* imageData=[NSData dataWithContentsOfURL:url];
UIImage *img=[UIImage imageWithData:imgData];
//执行主队列,刷新self.imageView
dispatch_async(dispatch_get_main_queue(),^{
self.imageView.image=img;
});
});
}
参考资料
《IOS开发指南 从HELLO WORLD到APP STORE上架 第5版》