- -(void)doDispatchBarrierAsync
- {
- NSLog(@"=====Dispatch Barrier Async 在并发对联中单独执行一个任务=====");
- //创建并发队列
- dispatch_queue_t concurrentDiapatchQueue=dispatch_queue_create("com.test.queue", DISPATCH_QUEUE_CONCURRENT);
- //此方法用于并发队列时打断其他线程,只执行队列中一个任务。
- dispatch_async(concurrentDiapatchQueue, ^{NSLog(@"0");});
- dispatch_async(concurrentDiapatchQueue, ^{NSLog(@"1");});
- dispatch_async(concurrentDiapatchQueue, ^{NSLog(@"2");});
- dispatch_async(concurrentDiapatchQueue, ^{NSLog(@"3");});
- dispatch_barrier_async(concurrentDiapatchQueue, ^{sleep(1); NSLog(@"4");});
- dispatch_async(concurrentDiapatchQueue, ^{NSLog(@"5");});
- dispatch_async(concurrentDiapatchQueue, ^{NSLog(@"6");});
- dispatch_async(concurrentDiapatchQueue, ^{NSLog(@"7");});
- dispatch_async(concurrentDiapatchQueue, ^{NSLog(@"8");});
- // ios 6 之后 ARC自动管理 dispatch_release(concurrentDiapatchQueue);
- //2014-04-18 11:25:09.142 GCD中得常用方法[15546:3007] 1
- //2014-04-18 11:25:09.142 GCD中得常用方法[15546:3503] 2
- //2014-04-18 11:25:09.142 GCD中得常用方法[15546:1303] 0
- //2014-04-18 11:25:09.142 GCD中得常用方法[15546:3603] 3
- //2014-04-18 11:25:10.145 GCD中得常用方法[15546:3603] 4
- //2014-04-18 11:25:10.146 GCD中得常用方法[15546:3603] 5
- //2014-04-18 11:25:10.146 GCD中得常用方法[15546:1303] 6
- //2014-04-18 11:25:10.146 GCD中得常用方法[15546:3007] 7
- //2014-04-18 11:25:10.146 GCD中得常用方法[15546:3503] 8
- //看打印结果,我们发现,在执行dispatch_barrier_async的时候5、6、7、8也没有并发执行,而是等4执行结束之后,才继续并发执行。
- //我们可以设想一个使用场景,对一个数组删除和读取的时候,如果正在读得瞬间删除了一条数据,导致下标改变,那就有可能出问题,甚至crash,这时候这个操作就能避免此类问题出现。
- }
- -(void)doDispatchSync
- {
- NSLog(@"=====Dispatch Sync 同步执行=====");
- //切记,千万别在执行Dispatch Sync方法的队列中调用自身队列,否则,死锁。
- dispatch_queue_t queue=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
- dispatch_sync(queue, ^{sleep(1);NSLog(@"1");});
- dispatch_sync(queue, ^{sleep(1);NSLog(@"2");});
- dispatch_sync(queue, ^{sleep(1);NSLog(@"3");});
- NSLog(@"4");
- //2014-04-18 11:47:20.512 GCD中得常用方法[15673:60b] 1
- //2014-04-18 11:47:21.513 GCD中得常用方法[15673:60b] 2
- //2014-04-18 11:47:22.514 GCD中得常用方法[15673:60b] 3
- //2014-04-18 11:47:22.515 GCD中得常用方法[15673:60b] 4
- /*从线程编号中我们发现,同步方法没有去开新的线程,而是在当前线程中执行队列,会有人问,上文说dispatch_get_global_queue不是并发队列,
- 并发队列不是应该会在开启多个线程吗?,这个前提是用异步方法。GCD其实是弱化了线程的管理,强化了队列管理,这使我们理解变得比较形象。*/
- }
- -(void)doDispatchAsyncF
- {
- NSLog(@"=====dispatch_async_f C方法调用异步=====");
- //应“天意”要求,这里给大家用一次“dispatch_async_f”方法,个人喜欢用block;
- // dispatch_async_f(queue, void *context, dispatch_function_t work)
- // queue:指定执行该work的队列,这个和用block一样
- // void *context:所使用的 application-defined(应用程序范围内有效的,也就是全局的)级别的参数。这是个C语法,void * 是一个无类型指针。也就是说,用它可以指向任何内存数据。
- // work:在指定队列(queue 参数)中要执行的方法。在该方法中,第一个参数所指代的数据,也就是dispatch_async_f方法所使用的第二个参数(void *context)所指带的数据。
- dispatch_queue_t queue=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
- int a = 1;
- dispatch_async_f(queue, &a, logNum);
- //如果用block就变得非常容易
- int i=2;
- dispatch_async(queue,^{NSLog(@"%i",i);});
- }
- void logNum(voidvoid *a)
- {
- NSLog(@"%i",(int )*(intint *)a);
- }
- -(void)doDispatchApply
- {
- NSLog(@"=====dispatch_async=====");
- //此方法可用于异步遍历,提高遍历的效率。
- NSArray *array=[[NSArray alloc]initWithObjects:@"0",@"1",@"2",@"3",@"4",@"5",@"6", nil nil];
- dispatch_queue_t queue=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
- dispatch_async(queue, ^{
- dispatch_apply([array count], queue, ^(size_t index) {
- NSLog(@"%zu=%@",index,[array objectAtIndex:index]);
- });
- });
- }
- -(void)doSuspendResunme
- {
- NSLog(@"=====dispatch_suspend/dispatch_resume 挂起/恢复=====");
- dispatch_queue_t concurrentDiapatchQueue=dispatch_queue_create("com.test.queue", DISPATCH_QUEUE_CONCURRENT);
- dispatch_async(concurrentDiapatchQueue, ^{
- for (int i=0; i<100; i++)
- {
- NSLog(@"%i",i);
- if (i==50)
- {
- NSLog(@"-----------------------------------");
- dispatch_suspend(concurrentDiapatchQueue);
- sleep(3);
- dispatch_resume(concurrentDiapatchQueue);
- }
- }
- });
- //此demo模拟当遇到符合某个特定值的时候挂起线程,然后等处理完之后恢复线程。
- }
- -(void)doSemaphore
- {
- NSLog(@"=====dispatch_semaphore 信号量=====");
- //dispatch_semaphore_signal 信号量+1;
- //dispatch_semaphore_wait 信号量-1, 当变为0后如果是DISPATCH_TIME_FOREVER,则永远等待;
- dispatch_semaphore_t semaphore = dispatch_semaphore_create(10);//为了让一次输出10个,初始信号量为10;
- dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
- for (int i = 0; i <100; i++)
- {
- dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);//每进来1次,信号量-1;进来10次后就一直hold住,直到信号量大于0;
- dispatch_async(queue, ^{
- NSLog(@"%i",i);
- sleep(2);
- dispatch_semaphore_signal(semaphore);//由于这里只是log,所以处理速度非常快,我就模拟2秒后信号量+1;
- });
- }
- //IOS 6 ARC自动管理 dispatch_release(semaphore);
- //这个demo的使用场景是为了防止并发数过多导致系统资源吃紧。
- //在这里不得不提到并发的真实工作原理,以单核CPU做并发为例,一个CPU永远只能干一件事情,那如何同时处理多个事件呢,聪明的内核工程师让CPU干第一件事情,一定时间后停下来,存取进度,干第二件事情以此类推,所以如果开启非常多的线程,单核CPU会变得非常吃力,即使多核CPU,核心数也是有限的,所以合理分配线程,变得至关重要。
- //讲到这也不得不提如何高效的发挥多核CPU的性能,如果让一个核心模拟传很多线程,经常干一半放下干另一件事情,那效率也会变低,所以我们要合理安排,将单一任务或者一组相关任务并发至全局队列中运算或者将多个不相关的任务或者关联不紧密的任务并发至用户队列中运算。
- }
- -(void)doDispatchOnce
- {
- NSLog(@"=====dispatch_once=====");
- //此方法都用于单例。
- static dispatch_once_t once;
- dispatch_once(&once,^{
- NSLog(@"只执行1次");
- });
- }
GCD常用使用方法
最新推荐文章于 2021-04-28 22:35:43 发布