Grand Central Dispatch(GCD) 是 Apple 开发的一个多核编程的较新的解决方法。它主要用于优化应用程序以支持多核处理器以及其他对称多处理系统。它是一个在线程池模式的基础上执行的并发任务。在 Mac OS X 10.6 雪豹中首次推出,也可在 iOS 4 及以上版本使用。GCD详细介绍参考:GCD详解
关于GCD的三种不同的线程队列理解分析:
一.dispatch_get_main_queue
主队列,也是串行队列,所有被添加到主队列中的线程都是主线程。
//MARK:主线程
- (void)doSomeThingsOnMainThread { dispatch_queue_t main_queue = dispatch_get_main_queue(); dispatch_async(main_queue, ^{ NSLog(@"1:%@",[NSThread currentThread]); }); dispatch_async(main_queue, ^{ NSLog(@"2:%@",[NSThread currentThread]); }); dispatch_async(main_queue, ^{ NSLog(@"3:%@",[NSThread currentThread]); }); dispatch_async(main_queue, ^{ NSLog(@"4:%@",[NSThread currentThread]); }); dispatch_sync(main_queue, ^{ NSLog(@"5:%@",[NSThread currentThread]); }); /* 2018-05-04 15:46:19.627674+0800 GCD几种线程理解[7802:451301] 1:<NSThread: 0x600000067340>{number = 1, name = main} 2018-05-04 15:46:19.627831+0800 GCD几种线程理解[7802:451301] 2:<NSThread: 0x600000067340>{number = 1, name = main} 2018-05-04 15:46:19.627977+0800 GCD几种线程理解[7802:451301] 3:<NSThread: 0x600000067340>{number = 1, name = main} 2018-05-04 15:46:19.628090+0800 GCD几种线程理解[7802:451301] 4:<NSThread: 0x600000067340>{number = 1, name = main} */ /* 1.从这里我们可以看出主线程队列也是个串行队列,所有被添加到主线程队列上的线程都是主线程,遵循先进先出规则,即FIFO. 2.在主线程队列中使用同步线程会导致主线程锁死. 3.被分配的线程都是同一个主线程. */ }
二.全局队列 dispatch_get_global_queue
//MARK:全局队列
- (void)doSomeThingsOnGlobalQueue { /* #define DISPATCH_QUEUE_PRIORITY_HIGH 2 #define DISPATCH_QUEUE_PRIORITY_DEFAULT 0 默认 #define DISPATCH_QUEUE_PRIORITY_LOW (-2) #define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN */ dispatch_queue_t global_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(global_queue, ^{ NSLog(@"1:%@",[NSThread currentThread]); }); dispatch_async(global_queue, ^{ NSLog(@"2:%@",[NSThread currentThread]); }); dispatch_async(global_queue, ^{ NSLog(@"3:%@",[NSThread currentThread]); }); dispatch_async(global_queue, ^{ NSLog(@"4:%@",[NSThread currentThread]); }); dispatch_sync(global_queue, ^{ NSLog(@"5:%@",[NSThread currentThread]); }); /* 2018-05-04 15:55:13.790857+0800 GCD几种线程理解[7957:458387] 5:<NSThread: 0x600000261200>{number = 1, name = main} 2018-05-04 15:55:13.790890+0800 GCD几种线程理解[7957:458418] 2:<NSThread: 0x60400046d400>{number = 4, name = (null)} 2018-05-04 15:55:13.790908+0800 GCD几种线程理解[7957:458417] 4:<NSThread: 0x60400046d700>{number = 5, name = (null)} 2018-05-04 15:55:13.790857+0800 GCD几种线程理解[7957:458416] 1:<NSThread: 0x60400046d800>{number = 3, name = (null)} 2018-05-04 15:55:13.790916+0800 GCD几种线程理解[7957:458421] 3:<NSThread: 0x60400046d8c0>{number = 6, name = (null)} */ /* 1.dispatch_get_global_queue 全局队列是一个并行队列,并有四种模式,优先级从高到低。 2.被分配的线程是随机的,同步线程被分配到当前环境下的线程上。 3.没有先后执行顺序。 */ }
三.
//MARK:用户队列 dispatch_queue_create
- (void)doSomeThingsOnUSerQueue_SERIAL { dispatch_queue_t user_queue = dispatch_queue_create("自定义queue", DISPATCH_QUEUE_SERIAL); dispatch_async(user_queue, ^{ NSLog(@"1:%@",[NSThread currentThread]); }); dispatch_async(user_queue, ^{ NSLog(@"2:%@",[NSThread currentThread]); }); dispatch_async(user_queue, ^{ NSLog(@"3:%@",[NSThread currentThread]); }); dispatch_async(user_queue, ^{ NSLog(@"4:%@",[NSThread currentThread]); }); dispatch_sync(user_queue, ^{ NSLog(@"5:%@",[NSThread currentThread]); }); /* 2018-05-04 16:02:40.567297+0800 GCD几种线程理解[8064:463826] 1:<NSThread: 0x60000027fc00>{number = 3, name = (null)} 2018-05-04 16:02:40.567512+0800 GCD几种线程理解[8064:463826] 2:<NSThread: 0x60000027fc00>{number = 3, name = (null)} 2018-05-04 16:02:40.567641+0800 GCD几种线程理解[8064:463826] 3:<NSThread: 0x60000027fc00>{number = 3, name = (null)} 2018-05-04 16:02:40.567740+0800 GCD几种线程理解[8064:463826] 4:<NSThread: 0x60000027fc00>{number = 3, name = (null)} 2018-05-04 16:02:40.567855+0800 GCD几种线程理解[8064:463792] 5:<NSThread: 0x604000067d00>{number = 1, name = main} */ /* 1.DISPATCH_QUEUE_SERIAL 从这里可以看出是一个串行队列,FIFO 2.异步线程,被分配到同一个异步线程上。 3.同步线程被分配到当前环境下的线程上。 */ }
- (void)doSomeThingsOnUSerQueue_CONCURRENT { dispatch_queue_t user_queue = dispatch_queue_create("自定义queue", DISPATCH_QUEUE_CONCURRENT); dispatch_async(user_queue, ^{ NSLog(@"1:%@",[NSThread currentThread]); }); dispatch_async(user_queue, ^{ NSLog(@"2:%@",[NSThread currentThread]); }); dispatch_async(user_queue, ^{ NSLog(@"3:%@",[NSThread currentThread]); }); dispatch_async(user_queue, ^{ NSLog(@"4:%@",[NSThread currentThread]); }); dispatch_sync(user_queue, ^{ NSLog(@"5:%@",[NSThread currentThread]); }); dispatch_barrier_async(user_queue, ^{ NSLog(@"6:%@",[NSThread currentThread]); }); dispatch_async(user_queue, ^{ NSLog(@"7:%@",[NSThread currentThread]); }); dispatch_async(user_queue, ^{ NSLog(@"8:%@",[NSThread currentThread]); }); /* 2018-05-04 16:11:29.918104+0800 GCD几种线程理解[8203:470574] 2:<NSThread: 0x60400026fb80>{number = 4, name = (null)} 2018-05-04 16:11:29.918104+0800 GCD几种线程理解[8203:470523] 5:<NSThread: 0x604000075ec0>{number = 1, name = main} 2018-05-04 16:11:29.918115+0800 GCD几种线程理解[8203:470576] 3:<NSThread: 0x600000471180>{number = 5, name = (null)} 2018-05-04 16:11:29.918125+0800 GCD几种线程理解[8203:470577] 1:<NSThread: 0x60400026fe00>{number = 3, name = (null)} 2018-05-04 16:11:29.918134+0800 GCD几种线程理解[8203:470575] 4:<NSThread: 0x600000470f00>{number = 6, name = (null)} 2018-05-04 16:11:29.918415+0800 GCD几种线程理解[8203:470575] 6:<NSThread: 0x600000470f00>{number = 6, name = (null)} 2018-05-04 16:11:29.919456+0800 GCD几种线程理解[8203:470574] 8:<NSThread: 0x60400026fb80>{number = 4, name = (null)} 2018-05-04 16:11:29.919456+0800 GCD几种线程理解[8203:470575] 7:<NSThread: 0x600000470f00>{number = 6, name = (null)} */ /* 1.DISPATCH_QUEUE_CONCURRENT 从这里看出是一个并行队列 2.同步线程被分配到当前环境下的线程上。 3.另外DISPATCH_QUEUE_CONCURRENT队列还可以用于栅栏函数,dispatch_barrier_async可以保证线程的执行顺序,在它之前被添加的 线程执行,之后的添加函数,等dispatch_barrier_async函数执行完之后,在开始执行。 */ }
另外还有一些常见GCD函数的使用
1.栅栏函数
- (void)doSomeThingsOnUSerQueue_CONCURRENT { dispatch_queue_t user_queue = dispatch_queue_create("自定义queue", DISPATCH_QUEUE_CONCURRENT); dispatch_async(user_queue, ^{ NSLog(@"1:%@",[NSThread currentThread]); }); dispatch_async(user_queue, ^{ NSLog(@"2:%@",[NSThread currentThread]); }); dispatch_async(user_queue, ^{ NSLog(@"3:%@",[NSThread currentThread]); }); dispatch_async(user_queue, ^{ NSLog(@"4:%@",[NSThread currentThread]); }); dispatch_sync(user_queue, ^{ NSLog(@"5:%@",[NSThread currentThread]); }); dispatch_barrier_async(user_queue, ^{ NSLog(@"6:%@",[NSThread currentThread]); }); dispatch_async(user_queue, ^{ NSLog(@"7:%@",[NSThread currentThread]); }); dispatch_async(user_queue, ^{ NSLog(@"8:%@",[NSThread currentThread]); }); /* 2018-05-04 16:11:29.918104+0800 GCD几种线程理解[8203:470574] 2:<NSThread: 0x60400026fb80>{number = 4, name = (null)} 2018-05-04 16:11:29.918104+0800 GCD几种线程理解[8203:470523] 5:<NSThread: 0x604000075ec0>{number = 1, name = main} 2018-05-04 16:11:29.918115+0800 GCD几种线程理解[8203:470576] 3:<NSThread: 0x600000471180>{number = 5, name = (null)} 2018-05-04 16:11:29.918125+0800 GCD几种线程理解[8203:470577] 1:<NSThread: 0x60400026fe00>{number = 3, name = (null)} 2018-05-04 16:11:29.918134+0800 GCD几种线程理解[8203:470575] 4:<NSThread: 0x600000470f00>{number = 6, name = (null)} 2018-05-04 16:11:29.918415+0800 GCD几种线程理解[8203:470575] 6:<NSThread: 0x600000470f00>{number = 6, name = (null)} 2018-05-04 16:11:29.919456+0800 GCD几种线程理解[8203:470574] 8:<NSThread: 0x60400026fb80>{number = 4, name = (null)} 2018-05-04 16:11:29.919456+0800 GCD几种线程理解[8203:470575] 7:<NSThread: 0x600000470f00>{number = 6, name = (null)} */ /* 1.DISPATCH_QUEUE_CONCURRENT 从这里看出是一个并行队列 2.同步线程被分配到当前环境下的线程上。 3.另外DISPATCH_QUEUE_CONCURRENT队列还可以用于栅栏函数,dispatch_barrier_async可以保证线程的执行顺序,在它之前被添加的 线程执行,之后的添加函数,等dispatch_barrier_async函数执行完之后,在开始执行。 */ }
2.dispatch_group_t函数
- (void)doSomeThingsOnGroupThead { dispatch_queue_t user_queue = dispatch_queue_create("自定义queue", DISPATCH_QUEUE_CONCURRENT); dispatch_group_t group = dispatch_group_create(); dispatch_group_async(group, user_queue, ^{ NSLog(@"1:%@",[NSThread currentThread]); }); dispatch_group_async(group, user_queue, ^{ NSLog(@"2:%@",[NSThread currentThread]); }); dispatch_group_async(group, user_queue, ^{ NSLog(@"3:%@",[NSThread currentThread]); }); dispatch_group_notify(group, user_queue, ^{ NSLog(@"4:%@",[NSThread currentThread]); }); dispatch_group_async(group, user_queue, ^{ NSLog(@"5:%@",[NSThread currentThread]); }); /* 2018-05-04 16:22:01.429294+0800 GCD几种线程理解[8372:479143] 1:<NSThread: 0x604000463e80>{number = 3, name = (null)} 2018-05-04 16:22:01.429294+0800 GCD几种线程理解[8372:479139] 2:<NSThread: 0x60000046e6c0>{number = 4, name = (null)} 2018-05-04 16:22:01.429309+0800 GCD几种线程理解[8372:479141] 5:<NSThread: 0x60000046e780>{number = 5, name = (null)} 2018-05-04 16:22:01.429320+0800 GCD几种线程理解[8372:479142] 3:<NSThread: 0x60000046f600>{number = 6, name = (null)} 2018-05-04 16:22:01.429593+0800 GCD几种线程理解[8372:479142] 4:<NSThread: 0x60000046f600>{number = 6, name = (null)} */ /* dispatch_group_notify 函数可以保证几个任务都执行完后,才执行下一个动作。无论添加先后顺序 多个网络请求时,如果需要等多个请求完成后处理,可以利用dispatch_gourp_enter和dispatch_group_leave,
dispatch_group_notify实现,如果要按顺序逐个请求,可以给每个请求加一个完成回调即可。*/}
3.信号量函数
//MARK:利用信号量实现阻塞效果
- (void)semaphore_t { //和创建信号量 dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); NSMutableArray *array = [NSMutableArray array]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ for (int i=0; i<10; i++) { [NSThread sleepForTimeInterval:1.0]; [array addObject:@(i)]; } dispatch_semaphore_signal(semaphore);//走车了1 }); long timeount = dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);//来车了1等待 if (timeount) { NSLog(@"请求超时"); } NSLog(@"array2:%@",array); }