出来工作已经一段时间了,但是对于大四才转程序的我,对很多程序方面的问题还是似懂非懂。很多时候学习起来也很迷茫,不知道自己往哪方面发展。于是乎很早之前就开始筹划写一些博客记录自己学习的过程。终于在工作之余抽出了时间写下这篇博客了,虽然是老生常谈,但是写下这些东西对于自己学习还是有很大帮助的。
GCD(Grand Central Dispatch)
学习GCD可以查看官方文档GCD官方文档,
弄懂GCD,首先我们该弄清楚同步
、异步
、串行
、并行
的概念
串行:是在同一时间执行一个线程,如果是同步所有的动作都在一个线程完成,如果是异步只需要开通一个子线程。
并行:同一时间执行多个线程,但是这些线程都是无序的。
同步:同一时间内只能执行一个操作,当这个操作完成后才能进行下一个操作。
异步:多个操作同时进行,返回的先后不确定
-(void)gcdSerial{
dispatch_queue_t queue1 = dispatch_queue_create("qianxiao_GCD", DISPATCH_QUEUE_SERIAL);
for (int i = 0; i < 5; i++) {
dispatch_sync(queue1, ^{
NSLog(@"sync:%@",[NSThread currentThread]);
});
}
for (int i = 0; i < 5; i++) {
dispatch_async(queue1, ^{
NSLog(@"async:%@",[NSThread currentThread]);
});
}
}
打印结果为:
轻量级交互
-(void)gcdConcurrent{
dispatch_queue_t queue2 = dispatch_queue_create("qianxiao_GCD", DISPATCH_QUEUE_CONCURRENT);
for (int i = 0; i < 5; i++) {
dispatch_sync(queue2, ^{
NSLog(@"sync:%@",[NSThread currentThread]);
});
}
for (int i = 0; i < 5; i++) {
dispatch_async(queue2, ^{
NSLog(@"async:%@",[NSThread currentThread]);
});
}
}
打印结果为:
轻量级交互
结论:同步dispatch_sync
不管是串行还是并行,都是在主线程中实现相关操作的。而dispatch_async
串行的时候只需要开启一个子线程,而在并行的时候开启不确定数目的子线程(异步并行少用,比较浪费资源)
弄清了以上的相关功能,我们下面说下关于group创建,废话不多说先看代码
-(void)createGCDGroup{
dispatch_queue_t queue = dispatch_queue_create("qianxiao_group", NULL);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{
NSLog(@"group_1:%@",[NSThread currentThread]);
});
dispatch_group_async(group, queue, ^{
NSLog(@"group_2:%@",[NSThread currentThread]);
[NSThread sleepForTimeInterval:3];
});
dispatch_group_async(group, queue, ^{
NSLog(@"group_3:%@",[NSThread currentThread]);
[NSThread sleepForTimeInterval:1];
});
dispatch_group_notify(group, queue, ^{
NSLog(@"group_notify");
});
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
NSLog(@"group_wait_after:%@",[NSThread currentThread]);
}
打印结果为:
轻量级交互
结论:
dispatch_group_t
是创建一个组,里面异步执行dispatch_queue_t
相关的任务dispatch_get_global_queue
是一个全局的异步队列
dispatch_group_notify
是一个汇总的过程,他会在group里面的任务执行完成之后才会回调回来。需要注意的是dispatch_barrier_async
,和dispatch_group_notify
很像,dispatch_barrier_async
是在该线程之前所有的操作做完之后才开始执行这个他之后线程做的操作。
dispatch_group_wait
是让上面所有的线程执行完成之后再继续执行下面的代码,但是这个会干扰主线程,让主线程也停止,所以此方法慎用。
dispatch_suspend()
, dispatch_resume()
这两个方法是对一个线程挂起和恢复运行,这里的挂起保证对该函数以后的线程操作进行暂停。这两个函数一定是要成对出现的。
dispatch_source_t
是一个监视某些类型事件的对象,当这些事件被触发时,他会自动将一个block放入一个dispatch queue中执行。他和dispatch_async
相比,dispatch_source_t
多了一个联结的功能,这也是dispatch_source_t
优势。接下来看一个小例子
-(void)gcdSource{
dispatch_queue_t globelQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, globelQueue);
dispatch_source_set_event_handler(source, ^{
unsigned long count = dispatch_source_get_data(source);
NSLog(@"count:%lu",count);
});
dispatch_resume(source);
dispatch_async(globelQueue, ^{
dispatch_source_merge_data(source, 5);
});
}
这段代码运行结果是5; dispatch_source_t
是一个挂起的程序(这里在我刚接触的时候被坑了很久),我们需要手动通过dispatch_resume
启动,然后用dispatch_source_merge_data(source, 5)
将结果汇总,用dispatch_source_get_data(source)
得到汇总结果。
定时器
直接上代码
-(void)gcdCountDown{
__block int count = 30;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,queue);
dispatch_source_set_timer(timer,dispatch_walltime(NULL, 0),1.0*NSEC_PER_SEC, 0); //1.0*NSEC_PER_SEC --> 每秒执行
dispatch_source_set_event_handler(timer, ^{
if (count < 0) {
dispatch_source_cancel(timer);
}else{
count--;
}
NSLog(@"%d",count);
});
dispatch_resume(timer);
}
自己总结:通过写这篇博客,我理清了一些以前模棱两可的知识点,其中也参照了一些其他人的博客,毕竟是记录自己学习的过程,只要有进步一切付出都是值得的。
如果你想了解更多的GCD知识看这篇文章
网友评论