GCD
Grand Central Dispatch是异步执行任务的技术之一。
GCD是苹果公司为多核的并行运算提出的解决方案
GCD会自动利用更多的CPU内核(比如双核、四核)
GCD会自动管理线程的生命周期(创建线程、调度任务、销毁线程)
程序员只需要告诉GCD想要执行什么任务,不需要编写任何线程管理代码
一个例子
<pre>
dispatch_async(queue, ^{
/*
*长时间处理
*/
/*
*长时间处理结束,主线程使用该处理结果
*
*/
dispatch_async(dispatch_get_main_queue(), ^{
/*
*只在主线程中可以执行的结果
*例如 更新UI
*/
});
});
其中queue是队列
block是任务
</pre>
在多线程编程中容易发生各种问题。比如多线程更新相同的数据、死锁、使用线程太多大量消耗内存等。采用GCD技术大大简化了复杂的多线程编程
Dispatch Queue
开发者要做的只是定义想执行的任务并追加到适当的Dispatch Queue中。
<pre>
dispatch_async(queue, ^{
/*
*想执行的任务
*/
});
</pre>
任务的取出遵循队列的FIFO原则:先进先出,后进后出。
另外在执行处理的时候存在两种Dispatch Queue,一种是等待现在执行中处理的Serial Dispatch Queue,另一种是不等待现在执行中处理的Concurrent Dispatch Queue。
并行视图 串行视图
创建 dispatch_queue_create()
dispatch_queue_create(const char *label, dispatch_queue_attr_t attr)
<pre>
dispatch_queue_t queue = dispatch_queue_create("gcd", NULL);
dispatch_queue_create("gcd", DISPATCH_QUEUE_CONCURRENT)
</pre>
注意:系统对于一个Serial Dispatch Queue就只生成并使用一个线程。如果生成200个Serial Dispatch Queue,那么就生成200个线程
但是每个queue里面的多个任务还是一个一个的执行。
多个线程更新相同数据是可以使用Serial Dispatch Queue
Main Dispatch Queue/Global Dispatch Queue
<pre>
dispatch_get_main_queue();
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//可并行执行的处理
dispatch_async(dispatch_get_main_queue(), ^{
//主线程中处理
});
});
</pre>
dispatch_set_target_queue
dispatch_queue_create()生成的Queue,使用与默认优先级Global Dispatch Queue相同执行优先级的线程。而变更生成的Queue的执行优先级需要使用dispatch_set_target_queue这个函数
<pre>
dispatch_set_target_queue(<#dispatch_object_t object#>, <#dispatch_queue_t queue#>)
指定第一个Queue与第二个Queue相同的优先级。
</pre>
dispatch_after
<pre>
在1s后将指定的block追加到Main Queue中执行
dispatch_after函数是指定时间追加而不是指定时间处理
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 1*NSEC_PER_SEC);
dispatch_after(time, dispatch_get_main_queue(), ^{
NSLog(@"wait");
});
</pre>
Dispatch Group
在追加到Dispatch Queue中的多个处理全部结束之后想执行结束处理,这种会经常出现。在使用Current Dispatch的情况下使用Dispatch Group就可以实现
<pre>
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{
NSLog(@"hehe1");
});
dispatch_group_async(group, queue, ^{
NSLog(@"hehe2");
});
dispatch_group_async(group, queue, ^{
NSLog(@"hehe3");
});
dispatch_group_async(group, queue, ^{
NSLog(@"hehe4");
});
dispatch_group_notify(group, queue, ^{
NSLog(@"over");
});
2016-06-09 17:21:02.564 GCD[2874:227806] hehe3
2016-06-09 17:21:02.564 GCD[2874:227802] hehe2
2016-06-09 17:21:02.564 GCD[2874:227804] hehe1
2016-06-09 17:21:02.564 GCD[2874:227813] hehe4
2016-06-09 17:21:02.565 GCD[2874:227813] over
</pre>
多个线程并行执行,所以追加处理执行的顺序不定,但是 over一定在最后才执行这里有一个好例子给大家
Dispatch Semaphore
Dispatch Semaphore是持有计数的信号,该基数是多线程编程中的计数信号类型。当计数为0时等待,计数为1或者大于1,减去1而不等待。
<pre>
//创建一个计数为0的信号
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
NSMutableArray *muArray = [[NSMutableArray alloc] init];
dispatch_async(queue, ^{
for (int i=0; i<100; i++) {
[muArray addObject:@(i)];
}
dispatch_semaphore_signal(semaphore); //计数+1
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"===>%d",[muArray count]);
2016-06-09 17:49:14.300 GCD[2984:246535] ===>100
如果没有则Dispatch Semaphore
2016-06-09 17:57:55.160 GCD[3023:249929] ===>0
</pre>
上例中创建一个计数为0的信号 等待
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);等待Dispatch Semaphore计数达到大于或者等于1。当计数达到或者大于1是,对该计数进行减法并从dispatch_semaphore_wait函数返回
通过dispatch_semaphore_signal(semaphore); 将Dispatch Semaphore计数+1
网友评论