iOS-进阶整理08 - GCD----多线程优化

一、GCD

GCD(Grand Central Dispatch)是Apple开发的一种多核编程技术。主要用于优化应用程序以支持多核处理器
GCD提供函数实现多线程开发,性能更高,功能更强大
首次发布在Mac OS X 10.6,iOS 4以上也可用


//定义一个回调函数  
void function(void* str)  
{  
    printf("回调函数  %s\n",str);  
    NSLog(@"当前线程--%@",[NSThread currentThread]);  
}  
  
//串行队列,一次只执行一个任务  
-(void)serialQueue  
{  
    //创建  
    dispatch_queue_t serialQuene = dispatch_queue_create("串行队列", DISPATCH_QUEUE_SERIAL);  
    //为队列中添加任务  
    //同步执行dispatch_sync,同步任务与当前的线程是一个线程,同步会阻塞当前线程  
    //异步执行dispatch_async  
    dispatch_sync(serialQuene, ^{  
        NSLog(@"我是串行队列,第一步");  
        NSLog(@"当前线程--%@",[NSThread currentThread]);  
    });  
    dispatch_async_f(serialQuene, "第二步", function);  
    dispatch_async(serialQuene, ^{  
        NSLog(@"第三步");  
         NSLog(@"当前线程--%@",[NSThread currentThread]);  
    });  
    dispatch_async(serialQuene, ^{  
        NSLog(@"第四步");  
         NSLog(@"当前线程--%@",[NSThread currentThread]);  
    });  
    dispatch_async(serialQuene, ^{  
        NSLog(@"第5步");  
         NSLog(@"当前线程--%@",[NSThread currentThread]);  
    });  
    dispatch_async(serialQuene, ^{  
        NSLog(@"第6步");  
         NSLog(@"当前线程--%@",[NSThread currentThread]);  
    });  
    dispatch_async(serialQuene, ^{  
        NSLog(@"第7步");  
        NSLog(@"当前线程--%@",[NSThread currentThread]);  
    });  
    dispatch_async(serialQuene, ^{  
        NSLog(@"第8步");  
        NSLog(@"当前线程--%@",[NSThread currentThread]);  
    });  
           
    NSLog(@"最下面,线程%@",[NSThread currentThread]);        
}  
//并行队列  
-(void)concurrentQuene  
{  
  //创建并行队列  
  dispatch_queue_t concurrent = dispatch_queue_create("并行队列", DISPATCH_QUEUE_CONCURRENT);  
  //添加任务  
  dispatch_sync(concurrent, ^{  
      NSLog(@"我是并行队列,第1步,当前线程--%@",[NSThread currentThread]);  
  });  
    
  dispatch_async_f(concurrent, "第二步", function);  
    
  dispatch_async(concurrent, ^{  
      NSLog(@"第3步,当前线程--%@",[NSThread currentThread]);  
  });  
  dispatch_async(concurrent, ^{  
      NSLog(@"第4步,当前线程--%@",[NSThread currentThread]);  
  });  
  dispatch_async(concurrent, ^{  
      NSLog(@"第5步,当前线程--%@",[NSThread currentThread]);  
  });  
  dispatch_async(concurrent, ^{  
      NSLog(@"第6步,当前线程--%@",[NSThread currentThread]);  
  });  
  dispatch_async(concurrent, ^{  
      NSLog(@"第7步,当前线程--%@",[NSThread currentThread]);  
  });  
  dispatch_async(concurrent, ^{  
      NSLog(@"第8步,当前线程--%@",[NSThread currentThread]);  
  });  
}  

全局队列

//系统提供的队列,全局队列,是并行的队列  
-(void)globalQueue  
{  
    //系统提供的全局队列  
    //第一个参数:优先级,DISPATCH_QUEUE_PRIORITY_DEFAULT 0,  LOW -2, HIGH 2, BACKGROUND INT16_MIN  
    //第二个参数:Flags that are reserved for future use. Always specify 0 for this parameter.  
    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);  
    //添加任务  
    dispatch_async(globalQueue, ^{  
        NSLog(@"全局队列0----%@",[NSThread currentThread]);  
    });  
    dispatch_async(globalQueue, ^{  
        NSLog(@"全局队列1----%@",[NSThread currentThread]);  
    });  
    dispatch_async(globalQueue, ^{  
        NSLog(@"全局队列2----%@",[NSThread currentThread]);  
    });  
    dispatch_async(globalQueue, ^{  
        NSLog(@"全局队列3----%@",[NSThread currentThread]);  
    });  
    dispatch_async(globalQueue, ^{  
        NSLog(@"全局队列4----%@",[NSThread currentThread]);  
    });  
    dispatch_async(globalQueue, ^{  
        NSLog(@"全局队列5----%@",[NSThread currentThread]);  
    });  
    dispatch_async(globalQueue, ^{  
        NSLog(@"全局队列6----%@",[NSThread currentThread]);  
    });  
    dispatch_async(globalQueue, ^{  
        NSLog(@"全局队列7----%@",[NSThread currentThread]);  
    });  
}  

全局队列和主队列结合使用


//GCD的常见使用方式,全局队列和主队列的结合使用  
-(void)globalAndMainQueue  
{  
    dispatch_async(dispatch_get_global_queue(0, 0), ^{  
        //在全局队列中处理耗时的操作,因为全局队列执行的任务是在子线程中,不会阻塞主线程  
        NSLog(@"子线程耗时操作");  
        dispatch_async(dispatch_get_main_queue(), ^{  
            //此时该block中所执行的任务是在主队列中,那么该任务就是在主线程中,在此处进行刷新UI的行为  
            NSLog(@"刷新UI");  
        });  
    });  
}  

gcd的其他方法


//GCD中让某些代码只执行一次  
-(void)onceToken  
{  
    static UIImage *image = nil;  
    static dispatch_once_t onceToken ;  
    dispatch_once(&onceToken, ^{  
        //此处的代码只会执行一次  
        image = [[UIImage alloc]init];  
        NSLog(@"只会执行一次的代码");  
    });  
}  
//GCD中的其他方法  
-(void)otherGCD  
{  
    //在延迟时间点执行任务  
    //1.从什么时间开始计算  
    //2.从此时间多少秒执行  
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(55 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{  
        NSLog(@"after 5秒延迟执行 --- %@",[NSThread currentThread]);  
    });  
//    sleep(5);线程沉睡  
      
    //重复执行  
    //1.重复执行的次数  
    //2.队列  
    dispatch_apply(3, dispatch_get_global_queue(0, 0), ^(size_t count) {  
        NSLog(@"在主队列重复执行3次 %ld",count);  
    });  
}  

gcd——group

//GCD 将任务添加到队列中  
-(void)groupGCD  
{  
    //dispatch_group_async可以实现监听一组任务是否完成,完成后得到通知执行其他的操作。这个方法很有用,比如你执行三个下载任务,当三个任务都下载完成后你才通知界面说完成的了。下面是一段例子代码:  
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);  
    dispatch_group_t group = dispatch_group_create();  
            
    dispatch_group_async(group, queue, ^{  
        [NSThread sleepForTimeInterval:1];  
        NSLog(@"group1");  
    });  
    dispatch_group_async(group, queue, ^{  
        [NSThread sleepForTimeInterval:2];  
        NSLog(@"group2");  
    });  
    dispatch_group_async(group, queue, ^{  
        [NSThread sleepForTimeInterval:3];  
        NSLog(@"group3");  
    });  
      
    //当所有group里面的任务执行完,就执行notify  
    //在执行notify之前至少给队列里放一个任务  
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{  
        NSLog(@"updateUi");  
    });  
}  

gcd_barrier

//数据库的读取  可以并发执行,通过GCD里面的并行队列实现  
//数据库的写入  只能串行执行,通过GCD里面的串行队列实现  
//但项目中,有读取和写入,通过dispatch_barrier_async实现,此任务执行的时候,其他任务停止执行  
  
-(void)barrierGCD  
{  
    //创建并发队列  
    dispatch_queue_t queue = dispatch_queue_create("concurrentTest", DISPATCH_QUEUE_CONCURRENT);  
      
    //添加任务  
    dispatch_async(queue, ^{  
        NSLog(@"这是第一个读取数据的任务。。。线程是:%@,是否主线程:%d",[NSThread currentThread],[[NSThread currentThread]isMainThread]);  
    });  
      
    dispatch_barrier_async(queue, ^{  
        NSLog(@"正在给数据库写入,阻塞其他任务");  
    });  
      
    dispatch_async(queue, ^{  
        NSLog(@"这是第二个读取任务。。。线程是:%@,是否主线程:%d",[NSThread currentThread],[[NSThread currentThread]isMainThread]);  
    });        
}  
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,384评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,845评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,148评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,640评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,731评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,712评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,703评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,473评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,915评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,227评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,384评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,063评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,706评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,302评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,531评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,321评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,248评论 2 352

推荐阅读更多精彩内容