GCD
GCD(Grand Central Dispatch)中央调度器
使用GCD只要理解两个东西 (任务 、队列);线程的创建和销毁都不需要程序员管理,非常方便好用。
一、基本使用
1、异步+并行队列 : 开启新的线程,多任务同时执行。
//创建队列 /* 创建并发队列 dispatch_queue_create(队列标签, 队列类型); 队列类型: DISPATCH_QUEUE_CONCURRENT 并行/并发 DISPATCH_QUEUE_SERIAL 串行 */ dispatch_queue_t queue1 = dispatch_queue_create("queue.label", DISPATCH_QUEUE_CONCURRENT); /* 获取全局并发队列 dispatch_get_global_queue(优先级:一般使用Defaul, 这个暂时没用,填0就可以了); 优先级:从上往下 DISPATCH_QUEUE_PRIORITY_HIGH 2 DISPATCH_QUEUE_PRIORITY_DEFAULT 0 DISPATCH_QUEUE_PRIORITY_LOW (-2) DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN */ dispatch_queue_t queue2 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);//一般使用全局并发队列 /* dispatch_async 异步 dispatch_sync 同步 */ dispatch_async(queue2, ^{ //任务 for (int i =0; i < 10; i++) { NSLog(@"---01----:%@",[NSThread currentThread]); } }); dispatch_async(queue2, ^{ //任务 for (int i =0; i < 10; i++) { NSLog(@"---02----:%@",[NSThread currentThread]); } }); dispatch_async(queue2, ^{ //任务 for (int i =0; i < 10; i++) { NSLog(@"---03----:%@",[NSThread currentThread]); } });
2、异步+串行队列 : 开启新的线程,单任务一个一个执行。
//创建队列 /* 创建并发队列 dispatch_queue_create(队列标签, 队列类型); 队列类型: DISPATCH_QUEUE_CONCURRENT 并行/并发 DISPATCH_QUEUE_SERIAL 串行 */ // dispatch_queue_t queue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); dispatch_queue_t queue = dispatch_queue_create("queue.label", NULL);//可以填NULL,代表串行队列 /* dispatch_async 异步 dispatch_sync 同步 */ dispatch_async(queue, ^{ //任务 for (int i =0; i < 10; i++) { NSLog(@"---01----:%@",[NSThread currentThread]); } }); dispatch_async(queue, ^{ //任务 for (int i =0; i < 10; i++) { NSLog(@"---02----:%@",[NSThread currentThread]); } }); dispatch_async(queue, ^{ //任务 for (int i =0; i < 10; i++) { NSLog(@"---03----:%@",[NSThread currentThread]); } });
3、异步+主队列 : 不启新的线程,串行执行。
//获取主队列 dispatch_queue_t queue = dispatch_get_main_queue(); /* dispatch_async 异步 dispatch_sync 同步 */ dispatch_async(queue, ^{ //任务 for (int i =0; i < 10; i++) { NSLog(@"---01----:%@",[NSThread currentThread]); } }); dispatch_async(queue, ^{ //任务 for (int i =0; i < 10; i++) { NSLog(@"---02----:%@",[NSThread currentThread]); } }); dispatch_async(queue, ^{ //任务 for (int i =0; i < 10; i++) { NSLog(@"---03----:%@",[NSThread currentThread]); } });
一般用于从子线程回到主线程
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);//一般使用全局并发队列 dispatch_async(queue, ^{ //任务 //这里使用dispatch_async,异步回到主线程,而不会阻塞当前线程继续往下执行,如果需要等待主线程执行完成再往下执行就使用同步dispatch_sync dispatch_async(dispatch_get_main_queue(), ^{ NSLog(@"回到主线程"); }); // NSLog(@"这里还有执行内容。。"); });
4、同步+串行队列 :不开启新的线程,在主线程中执行。
//同步只可以用串行队列,就算设置为DISPATCH_QUEUE_CONCURRENT并行队列也是无效的 //创建队列 // dispatch_queue_t queue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); dispatch_queue_t queue = dispatch_queue_create("queue.label", NULL);//可以填NULL,代表串行队列 /* dispatch_async 异步 dispatch_sync 同步 */ dispatch_sync(queue, ^{ //任务 for (int i =0; i < 10; i++) { NSLog(@"---01----:%@",[NSThread currentThread]); } }); dispatch_sync(queue, ^{ //任务 for (int i =0; i < 10; i++) { NSLog(@"---02----:%@",[NSThread currentThread]); } }); dispatch_sync(queue, ^{ //任务 for (int i =0; i < 10; i++) { NSLog(@"---03----:%@",[NSThread currentThread]); } });
5、同步+主队列 : 相互等待,造成线程堵塞,不执行,所以不能这么使用。
NSLog(@"synMain -- start"); //获取主队列 dispatch_queue_t queue = dispatch_get_main_queue(); /* dispatch_async 异步 dispatch_sync 同步 */ dispatch_sync(queue, ^{ //任务 NSLog(@"---01----:%@",[NSThread currentThread]); }); NSLog(@"synMain -- end"); //打印结果 只会打印第一句 synMain -- start 然后就不执行了
6、barrier 特点:先执行barrier之前所以队列中的任务,再执行barrier的任务,等barrier的任务执行完成,再执行在队列中barrier之后的所有任务。
dispatch_queue_t queue = dispatch_queue_create("12312312", DISPATCH_QUEUE_CONCURRENT); dispatch_async(queue, ^{ NSLog(@"----1-----%@", [NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"----2-----%@", [NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"----3-----%@", [NSThread currentThread]); }); dispatch_barrier_async(queue, ^{ NSLog(@"----barrier-----%@", [NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"----4-----%@", [NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"----5-----%@", [NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"----6-----%@", [NSThread currentThread]); }); //执行结果:现在并发执行 1 2 3任务,再执行barrier任务 ,再并发执行 4 5 6 任务。
7、延迟执行
//默认放在dispatch_get_main_queue主队列中执行,可以改 //延迟2秒 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ //延迟执行的代码 }); //其他方式 // [self performSelector:@selector(run) withObject:nil afterDelay:2.0]; // [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:NO];
8、一次性代码 : 用于单利比较多。
//一次性代码 static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ //执行一次性代码,在整个程序运行期间只会执行一次。 });
9、快速迭代/快速遍历 :开启多个线程同时执行任务。
//会快速开不同的线程去执行 //dispatch_apply(执行次数, 队列, ^(size_t index); dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_apply(10, queue, ^(size_t index) { //快速迭代的代码,如:资料迁移。。等等。 });
10、队列组
//创建一个队列组 dispatch_group_t group = dispatch_group_create(); //创建一个队列 // 0代表默认的优先级DISPATCH_QUEUE_PRIORITY_DEFAULT dispatch_queue_t queue = dispatch_get_global_queue(0, 0); // 创建组 dispatch_group_async(group, queue, ^{ //第一个组的操作 // 比如:请求1。。。 的代码 }); // 创建组 dispatch_group_async(group, queue, ^{ //第二个组的操作 // 比如:请求2。。。 的代码 }); // dispatch_group_notify(group, dispatch_get_main_queue(), ^{ //当队列组都执行完成后就执行这里 NSLog(@"两个队列中的任务都执行完成了"); });