在移动App开发中,用户体验是我们在开发过程中必须考虑的问题,实时的相应用户的交互事件,是对一个App最基本的要求,因此程序的并行就显得尤其重要,因此在iOS中,程序的并行并不仅仅是为了加快某些操作的速度,更重要的我们是为了不要阻塞用户在主线程上的交互。iOS提供给我们不同级别的并行的接口,包括NSThread、Grand Central Dispatch(GCD)和NSOperationQueue,来满足我们在不同情形下的需要。
不同的api使用的复杂程度也不同,GCD和NSOperationQueue是建立在NSThread的基础之上,提供给了我们更加高层次的抽象,因此在使用中,我们应该尽量的使用GCD与NSOperationQueu,主要有一下原因:
- GCD和NSOperationQueue提供给了我们更加友好的接口,使用起来更加方便灵活
- GCD和NSOperationQueue仍然是以NSThread为基础来实现的,他们的本质是在系统中维护了一个线程池。当我们放入其中的任务被运行时,运行的单位仍然是线程池中的线程
- GCD和NSOperationQueue可以根据系统当前的繁忙状态来决定线程池中可以并发的线程数,这样可以防止过多的线程同时并发,导致系统性能的下降。
这里我主要是总结一下并行库的一些知识,还有一个小的Demo,展示了api的基本用法。
GCD是iOS提供的比较便捷的并行api,我们可以很方便的将包含我们操作的block放在GCD的dispatch queue
当中,然后任务就会在线程池中运行。iOS提供给了我们五中不同优先级的dispatch queue,三种不同优先级的背景队列,主线程对应的main queue,以及一个用户IO 操作的背景队列。我们也可以通过系统提供的接口,自己创建新的dispatch queue。
####Dispatch Queue
一般情况下,系统提供的队列就可以满足我们的要求1
dispatch_queue_t dispatch_get_global_queue(long priority, unsigned long flags)
我们也可以使用系统api dispatch_queue_create
创建自己的队列,并指定队列的类型(串行队列或者并行队列),然后利用dispatch_async
或者dispatch_sync
将block放入队列中执行,一旦我们将操作放入队列中之后,我们便失去了对这些操作的控制,完全由系统决定他们的实行时间,如果你需要在某些时候取消队列中的操作,那么你需要使用NSOperationQueue。
#####多线程时的资源访问的保护
由于我们的操作在线程池中时并行执行的(除非你的dispatch queue为顺序的),因此如果我们操作中有对资源的写操作,那么我们就需要实现资源的互斥访问,可以通过dispatch_barrier_async
来方便的做到这一点1
2
3
4
5
6
7dispatch_queue_t queue = dispatch_queue_create("concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
//if we want to add an item to array , and this method is called in blocks in the queue
- (void)insertString:(NSString*)str{
dispatch_barrier_async(queue, ^{
[self.array addObject:str];
});
}dispatch_barrier_async
确保了我们所有的插入操作都是安全的,它确保了addObject
语句在queue中所有在其之前插入的block执行完之后才执行。
#####Dispatch Group
Dispatch Group的作用是我们可以集中的处理属于同一group的block,比如我们想要在某几个block全都执行完毕后,将他们的执行结果整合起来:1
2
3
4
5
6
7
8
9
10
11
12
13dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(0,0);
dispatch_group_async(group,queue,^{
//some operation
});
dispatch_group_async(group,queue,^{
//some other operation
});
//perform some tasks when all operations are done
dispatch_group_notify(group, dispatch_get_main_queue(),^{
MyLabel.setText(@"All operations are done");
});
只有当同一group当中的所有block都执行完之后,MyLabel
才会发出通知。
GCD还有很多其他的使用和实现的细节,你可以通过文档还获得更多的内容