标签:c语言 serial sof imei 获取 central 效率 案例 upload
①什么是GCD
全称是Grand Central Dispatch,可译为“牛逼的中央调度器”,纯C语言,提供了非常多强大的函数
GCD的优势
GCD是苹果公司为多核的并行运算提出的解决方案
GCD会自动利用更多的CPU内核(比如双核、四核)
GCD会自动管理线程的生命周期(创建线程、调度任务、销毁线程)
程序员只需要告诉GCD想要执行什么任务,不需要编写任何线程管理代码
②GCD2个核心概念
1>任务:执行什么操作
2>队列:用来存放任务
GCD使用步骤
//?1.定制任务 确定想做的事情 //?2.将任务添加到队列中 GCD会自动将队列中的任务取出,放到对应的线程中执行 //任务的取出遵循队列的FIFO原则:先进先出,后进后出
程序员要做的是将任务添加到队列,队列按照程序员指定的方式调度任务。
③同步/异步-并发/串行
同步:一个人没有结束,就不会执行下一个任务
异步:不用等待任务执行完毕,就会执行下一个任务
并发和串行主要影响:任务的执行方式
并发:允许多个任务同时执行
串行:一个任务执行完毕后,再执行下一个任务
1>同步执行(sync这一句不执行,就不会执行下一句)
dispatch_sync(dsipatch_queue_t queue, dispatch_block_t block);//queue 队列;block 任务
//同步执行方法:(sync):这一句不执行完成,就不会执行下一个任务。同步线程是不会开启子线程 //1.创建队列 dispatch_queue_t q = dispatch_get_global_queue(0, 0); //2.将任务添加到队列中 //2.1定义一个任务--block void (^tasks)(void) = ^{ NSLog(@"%@",[NSThread currentThread]);//主线程 }; //2.2添加任务到队列,并且会执行 dispatch_sync(q, tasks);
2>异步执行(如果任务没有完成,可以不等待,异步执行下一个任务[具备开启线程的能力])
dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
//异步执行任务 如果任务没有执行完毕,可以不要等待,异步执行下一个任务。具备开启线程的能力。异步通常是多线程的代名词; //1.创建队列 并发队列 dispatch_queue_t q = dispatch_get_global_queue(0, 0); //2.将任务添加到队列中 //2.1定义一个任务--block void (^tasks)(void) = ^{ NSLog(@"%@",[NSThread currentThread]);//子线程 }; //3添加任务到队列 dispatch_async(q, tasks);
同步和异步的区别:
//同步:只能在当前线程中执行任务,不具备开启新线程的能力 //异步:可以在新的线程中执行任务,具备开启新线程的能力
④线程间通信:
//1指定任务的执行方法--异步 dispatch_async(dispatch_get_global_queue(0, 0), ^{ //耗时操作 NSLog(@"%@",[NSThread currentThread]); //更新UI dispatch_async(dispatch_get_main_queue(), ^{ NSLog(@"更新UI%@",[NSThread currentThread]); }); });
利用GCD来加载图片
dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSURL * url = [NSURL URLWithString:@"https://a-ssl.duitang.com/uploads/item/201503/09/20150309162548_LnTA3.thumb.700_0.jpeg"]; NSData * data = [NSData dataWithContentsOfURL:url]; UIImage * image = [UIImage imageWithData:data]; //更新UI dispatch_async(dispatch_get_main_queue(), ^{ self.imageView.image = image; [self.imageView sizeToFit]; self.scrollView.contentSize = image.size; }); });
从子线程回到主线程
dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // 执行耗时的异步操作... dispatch_async(dispatch_get_main_queue(), ^{ // 回到主线程,执行UI刷新操作 }); });
⑤队列:
//-串行队列:一个接着一个地执行任务 //-并发队列:可以同时调度多个任务 //-任务执行函数(任务都需要在线程中执行) //-同步执行:当前的任务不完成,不会执行下一个任务 //-异步执行:当前任务不完成,同样执行下一个任务 //-同步执行:不会到线程池里面去获取子线程 //-异步执行:只要有任务,就会到线程池里面去获取子线程(主队列除外) 小结: // -- 开不开线程取决于执行任务的函数,同步不开,异步开; // -- 开几条线程,取决于队列,串行开一条,并发开多条(异步)由CPU决定条数
队列的类型
1->并发队列(Concurrent Dispatch Queue)
可以让多个任务并发(同时)执行(自动开启多个线程同时执行任务)
并发功能只有在异步(dispatch_async)函数下才有效
使用dispatch_queue_create 函数创建队列
dispatch_queue_t dispatch_queue_create(const char *label, // 队列名称 dispatch_queue_attr_t attr); // 队列的类型
dispatch_get_global_queue 获取全局的并发队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_queue_t queue = dispatch_queue_create("com.520it.queue", DISPATCH_QUEUE_CONCURRENT); GCD默认已经提供了全局的并发队列,供整个应用使用,可以无需手动创建 使用dispatch_get_global_queue函数获得全局的并发队列 dispatch_queue_t dispatch_get_global_queue( dispatch_queue_priority_t priority, // 队列的优先级 unsigned long flags); // 此参数暂时无用,用0即可
全局并发队列的优先级
#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 q = dispatch_queue_create("CC_GCD8", DISPATCH_QUEUE_CONCURRENT); for (int i = 0; i<10; i++) { dispatch_async(q, ^{ NSLog(@"%@ %d",[NSThread currentThread],i); }); } /* 电量优化、流量优化 全局队列&串行队列: 全局队列:并发,能够调度多个线程,执行效率高-耗电! 串行队列:一个一个执行,执行效率低 - 省电 判断依据:根据用户的上网方式 Wifi:可以多开线程! 流量:尽量少开线程 几个典型的耗电场景: 1.定位,GPS定位 2.网络传输,在非Wifi环境 3.CPU频率 4.内存调度频率 5.后台运行! */
2>串行队列(Serial Dispatch Queue)
让任务一个接着一个地执行(一个任务执行完毕后,再执行下一个任务)
GCD中获得串行有2种途径
1>>使用dispatch_queue_create函数创建串行队列
// 创建串行队列(队列类型传递NULL或者DISPATCH_QUEUE_SERIAL) dispatch_queue_t queue = dispatch_queue_create("com.520it.queue", NULL);
2>>使用主队列(跟主线程相关联的队列)
//主队列是GCD自带的一种特殊的串行队列 放在主队列中的任务 //都会放到主线程中执行 //使用dispatch_get_main_queue()获得主队列 dispatch_queue_t queue = dispatch_get_main_queue();
3->GCD调度组 dispatch_group_t
//1.队列 dispatch_queue_t q = dispatch_get_global_queue(0, 0); //2.调度组 dispatch_group_t g = dispatch_group_create(); //3.添加任务,将队列调度任务。任务完成的时候,能够提醒 dispatch_group_async(g, q, ^{ NSLog(@"download A %@",[NSThread currentThread]); }); dispatch_group_async(g, q, ^{ [NSThread sleepForTimeInterval:1.0]; NSLog(@"download B %@",[NSThread currentThread]); }); dispatch_group_async(g, q, ^{ [NSThread sleepForTimeInterval:1.0]; NSLog(@"download C %@",[NSThread currentThread]); }); //4.当所有任务执行完毕后,通知 // dispatch_group_notify(g, q, ^{ // NSLog(@"OK %@",[NSThread currentThread]); // }); dispatch_group_notify(g, dispatch_get_main_queue(), ^{ //更新UI,通知用户 NSLog(@"OK %@",[NSThread currentThread]);//1 }); NSLog(@"Come Here ");
dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block);
这个函数要等在前面的任务执行结束后它才执行,而且它后面的任务等它执行完成之后才会执行。(这个queue不能是全局的并发队列)
⑥案例
1>主线程同步死锁dispatch_sync
//主队列: 专门负责在主线程上调度任务的一个队列!...>>不会开线程 //1.队列 dispatch_queue_t t = dispatch_get_main_queue(); //dispatch_sync 一个接一个造成死锁 会崩溃 //同步任务 dispatch_sync(t, ^{ NSLog(@"%@",[NSThread currentThread]); }); NSLog(@"COme here");
2>主线程同步不死锁dispatch_async
void (^task)(void) = ^{ NSLog(@"这里 !!! %@",[NSThread currentThread]); //1.队列 dispatch_queue_t t = dispatch_get_main_queue(); //dispatch_sync 一个接一个造成死锁 会崩溃 //同步任务 dispatch_sync(t, ^{ NSLog(@"%@",[NSThread currentThread]); }); }; dispatch_async(dispatch_get_global_queue(0, 0), task);
3>
//MARK:串行队列,同步执行 会不会开辟线程?不能【串并行不能决定是否开启子线程;异步才可以开启子线程】顺序执行吗?是 //MARK:串行队列,异步执行 串行 决定怎么拿任务 会不会开辟线程?会顺序执行吗?会 是 //MARK: 并发队列,异步执行: //会不会开辟线程? 顺序执行吗? comeHere //会 不是 不确定 //MARK: 并发队列,同步执行: //会不会开辟线程? 顺序执行吗? comeHere //不会 是 最后 //MARK: 同步任务加强 在开发中,通常耗时操作放在后台执行,有的时候,任务之间有依赖关系 例如:登录》支付、下载 利用同步任务,能做到任务依赖关系,前一个任务是同步任务,不执行完,队列就不会调度后面的任务 //MARK:增强版同步任务 队列调度多个任务之前,指定一个同步任务,让所有的异步,等待同步任务执行完成,就是依赖关系。同步任务就相当于一个锁
标签:c语言 serial sof imei 获取 central 效率 案例 upload
原文地址:https://www.cnblogs.com/StevenHuSir/p/iOS_GCD.html