用GCD创建多线程
GCD是苹果推荐的多线程方案,通常应用的场景是当程序需要做复杂的耗时的计算或操作的时候。比如发送网络请求,下载大图片等等。如果将这些都交由主线程来执行,那么主线程将无法响应用户的界面操作,非常影响用户体验。
这时候,将这些耗时任务交给子线程,就变成非常必要。GCD则是一套由C语言写的库。
- (void)viewDidLoad { [super viewDidLoad]; NSAssert(_image, @"Image not set; required to use view controller"); self.photoImageView.image = _image; //Resize if neccessary to ensure it's not pixelated if (_image.size.height <= self.photoImageView.bounds.size.height && _image.size.width <= self.photoImageView.bounds.size.width) { [self.photoImageView setContentMode:UIViewContentModeCenter]; } dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ // 1 UIImage *overlayImage = [self faceOverlayImageFromImage:_image]; dispatch_async(dispatch_get_main_queue(), ^{ // 2 [self fadeInNewImage:overlayImage]; // 3 }); }); }
如上面的代码所显示,我们通常复杂任务交了子线程~即是这样:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)
dispatch_async 为创建一个异步执行的任务,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)之后放在全局队列,也就是一个系统的并行队列。这样,代码则会在子线程中执行,并且保证了线程能顺利执行完。
而如果采用了住队列,结果则是变为异步就没有得到想要的效果了。最后还是会由主线程来执行任务的。所以需要用到多线程的时候,我们选择的一般是并行队列异步执行。
而当需要更新界面的时候,有一点必须要注意的是,也就是当需要访问UIkit的时候是必须要在主线程中进行,所以便需要使用:
dispatch_async(dispatch_get_main_queue(), ^{ // 2 [self fadeInNewImage:overlayImage]; // 3 });
上面的代码来回到主线程,完成界面相关操作。但凡需要更新界面,记得拿到住队列~~至于,如果这个地方,我们使用的是 dispatch_sync 后面再回到主线程的话, 会怎么样呢~答案就是阻塞主线程。因为主线程时刻都在执行任务,而我们突然加入一个同步执行的任务到住队列,则主线程正在执行的任务,和这个加上的任务互相等待,造成死锁了。~~所以无论如何,必须要记得,不能够使用主队列/串行队列同步执行了!!
//dispatch_syn(dispatch_get_main_queue(), ^{
//NSLog(@"3");
//死锁原因
//1:dispatch_sync在等待block语句执行完成,而block语句需要在主线程里执行,所以dispatch_sync如果在主线程调用就会造成死锁
//2:dispatch_sync是同步的,本身就会阻塞当前线程,也即主线程。而又往主线程里塞进去一个block,所以就会发生死锁。
//});
多线程相关好文章:https://github.com/nixzhu/dev-blog/blob/master/2014-04-19-grand-central-dispatch-in-depth-part-1.md
http://www.jianshu.com/p/0b0d9b1f1f19
http://www.jianshu.com/p/d3f954582231