多线程---GCD
一,什么是GCD?
GCD (Grand Center Dispatch),宏大(牛逼)的中央调度。Apple开发的一个多核编程的解决方法。在iOS所有实现多线程的方案中(NSThread,NSOperation&NSOperationQueue、GCD ),GCD应该是最有魅力的,因为GCD本身是苹果公司为多核的并行运算提出的解决方案。GCD在工作时会自动利用更多的CPU内核(比如双核、四核),GCD会自动管理线程的生命周期(创建线程、调度任务、销毁线程)。GCD是基于C语言的,因此我们在编写GCD相关代码的时候,面对的函数,而不是方法。如果使用GCD,完全由系统管理线程,我们不需要编写线程代码。只需定义想要执行的任务,然后添加到适当的调度队列(dispatch queue)。GCD会负责创建线程和调度你的任务,系统直接提供线程管理。
二、三种多线程的优缺点?
1.NSThread:
优点:NSThread ⽐比其他两个轻量级;缺点:需要⾃自⼰己管理线程的⽣生命周期,线程同步。线程同步对数据的加锁会有⼀一定的系统开销;
2.NSOperation&NSOperationQueue:
优点:不需要关⼼心线程管理,数据同步的事情,可以把精⼒力放在⾃自⼰己需要执⾏行的操作上。 Cocoaoperation相关的类是NSOperation,NSOperationQueue。NSOperation是个 抽象类,使⽤用它必须⽤用它的⼦子类,可以实现它或者使⽤用它定义好的两个⼦子类: NSInvocationOperation 和 NSBlockOperation。创建NSOperation⼦子类的对象,把对象 添加到NSOperationQueue队列⾥里执⾏行。
3.GCD:
Grand Central Dispatch (GCD)是Apple开发的⼀一个多核编程的解决⽅方法。在iOS4.0开始 之后才能使⽤用。GCD是⼀一个替代诸如NSThread, NSOperationQueue,NSInvocationOperation等技术的很⾼高效和强⼤大的技术。现在的iOS系统都升级到6了, 所以不⽤用担⼼心该技术不能使⽤用。
三,概念:
GCD中有2个核心概念
(1)任务:执行什么操作
(2)队列:用来存放任务
GCD的使用就2个步骤:(1)定制任务(2)确定想做的事情
1. 将任务添加到队列中,GCD会自动将队列中的任务取出,放到对应的线程中执行。
2. 任务的取出遵循队列的FIFO原则:先进先出,后进后出。
3.添加的异步任务会创建子线程,在子线程执行;而并发任务在主线程中执行。
4.同步任务中延时会阻塞该任务所在的线程。
四、使用示例
1.添加自定义队列;
//创建并发队列 dispatch_queue_t user= dispatch_queue_create("user", DISPATCH_QUEUE_CONCURRENT); //创建串行队列 //dispatch_queue_t user= dispatch_queue_create("user", DISPATCH_QUEUE_CONCURRENT); //添加异步任务 dispatch_async(user, ^{ [NSThread sleepForTimeInterval:1]; printf("2"); });
2.全局(并行)队列;
/** * 得到全局队列(并发队列) * * @param DISPATCH_QUEUE_PRIORITY_DEFAULT 队列的优先级 * @param 0 留作将来使用。传递其他任何非零值可能会导致一个NULL返回值。 * * @return 返回请求的全局队列,如果所请求的全局队列不存在则返回NULL。 */ dispatch_queue_t queue=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); printf("0\n"); dispatch_async(queue, ^{ dispatch_sync(queue, ^{ [NSThread sleepForTimeInterval:5]; printf("1\n"); }); dispatch_async(queue, ^{ printf("2\n"); }); printf("3\n"); }); printf("4\n");
输出结果为0 4 1 3 2 ,因为1所在的任务为同步任务,阻塞了其所在的子线程。
3.组队列;
/** * ——labe的值从1依次变为99 * * @return */ dispatch_group_t group=dispatch_group_create(); dispatch_queue_t queue=dispatch_queue_create("user", DISPATCH_QUEUE_SERIAL); for (int i=0; i<100; i++) { dispatch_group_async(group, queue, ^{ [NSThread sleepForTimeInterval:0.1]; dispatch_async(dispatch_get_main_queue(), ^{ _lab.text=[NSString stringWithFormat:@"%d",i]; }); }); } //为对象设置目标队列 // dispatch_set_target_queue(queue, dispatch_get_main_queue()); dispatch_group_notify(group, queue, ^{ printf("OK"); });
有些变量只需要初始化一次(如从文件中读取配置参数,读取设备型号等等),可以使用dispatch_once来进行读取优化,保证只调用API一次,以后就只要直接访问变量即可
范例如下:
- static BOOL isTestMode;
- + (BOOL)isTestMode
- {
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- NSNumber* obj = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFResourceTest"];
- isTestMode = [obj boolValue];
- });
- return isTestMode;
- }
在软件工程中,单例是一种用于实现单例的数学概念,即将类的实例化限制成仅一个对象的设计模式。
单例是一种类,该类只能实例化一个对象。
void dispatch_once( dispatch_once_t *predicate, dispatch_block_t block);
如果被多个线程调用,该函数会同步等等直至代码块完成。
+ (AccountManager *)sharedManager {
static AccountManager *sharedAccountManagerInstance = nil;
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
sharedAccountManagerInstance = [[self alloc] init];
});
return sharedAccountManagerInstance;
}
AccountManager *accountManager = [AccountManager sharedManager];
AccountManager *accountManager = [[AccountManager alloc] init];