GCD技术
多线程编程的三个技术  NSThread NSOperation GCD
1.GCD(Grand central Dispatch:宏大的中央调度)
       1) 是用纯C语言实现的.提供了非常多而且强大的函数,可以提高代码的执行效率和多核的利用率
       2) 是在Mac OS X 10.6 雪豹系统  IOS4引入的一种新一代的多线程编程技术
        2.1) 它是由苹果公司为多核的并行运算提出的解决方案
        2.2) 它会自动利用更多的处理器核心
        2.3) 不用关心线程代码,GCD会负责创建线程和调度任务
       3) 核心概念
            任务:执行什么功能,准备执行的代码
            队列:用来存放(调度)任务的.先进先出FIFO,后添加进来的任务在队列末端,但是执行的时机不好说
       4) 使用步骤
            4.1) 先制定任务(确定想做什么事)
            4.2) 把任务添加到适当的队列中即可
         说明:GCD会自动将队列中的任务取出,放到对应的线程中执行
       5) 区分一下名词
        5.1) 同步和异步的区别
         同步和异步是相对于另外一个任务而言的
        同步:在当前线程执行,第一个任务不执行完,第二个任务不会开始
        异步:在另一条线程中执行,不管第一个有没有执行完,都会开始第二个

5.2) 并发和串行队列的区别
         并发和串行是相对于多个任务而言的
       并发队列:在异步的情况下,多个任务并发执行
       串行队列:多个任务会按照顺序执行
    
        5.3) 并行与并发的区别
          并发说的是多任务,并行说的是多线程
          并行要求并发,并发并不能保证并行(单核)
     */
1..自定义:串行队列
dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL);
3.串行队列的异步任务(非常有用)
     特点:会创建新线程(只有一个),任务按照顺序执行
       这是斯坦福大学极力推荐的写法
     优点:不会卡死,任务顺序执行的话方便调试
     缺点:只开一个线程,并发性不强
    /*
.自定义:并发队列
1.创建并发队列
     先敲dispatch
     参数1) C的字符串:队列的唯一标识符(域名反写)
     参数2) 队列的类型:SERIAL(NULL)串行  CONCURRENT并发
     */
    dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_CONCURRENT);
    /*
     2.并发队列的同步任务
     特点:不会创建新线程,任务按照顺序执行(然并卵)
     */
#pragma mark - 2.系统自带的全局队列
- (void)gcdDemo3 {
    /*
     1.全局队列
     参数1) 队列的优先级:有四种
     参数2) 标记:为了以后准备的一个参数,填0
     */
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
   
    /*
     2.全局队列的同步任务
     */
    for(int i = 0; i < 100; i ++) {
        dispatch_sync(queue, ^{
            NSLog(@"1:%d----%@",i,[NSThread currentThread]);
        });
    }
   
    /*
     3.全局队列的异步任务
     */
    for(int i= 0; i < 100; i++){
        dispatch_async(queue, ^{
            NSLog(@"2:%d----%@",i,[NSThread currentThread]);
        });
    }
}
#pragma mark - 2.系统自带的主队列
- (void)gcdDemo4 {
    /*
     1.主队列:一般用来UI操作
     */
    dispatch_queue_t queue = dispatch_get_main_queue();
   
    /*
     2.主队列的同步任务:造成一个现象"死锁"
     这个写法不会出现
     for(int i = 0; i < 100; i ++) {
     dispatch_sync(queue, ^{
     NSLog(@"1:%d----%@",i,[NSThread currentThread]);
     });
     }
     */
  
    /*
     3.主队列的异步任务(串行的)
     在主线程中顺序执行
     */
    for(int i= 0; i < 100; i++){
        dispatch_async(queue, ^{
            NSLog(@"2:%d----%@",i,[NSThread currentThread]);
        });
    }

}
/*
 小总结
   1.无论什么队列和什么任务,线程的创建和回收不需要程序猿管理,由队列负责
   2.GCD在后端有一个线程池,自己决定block代码块在哪个线程中执行
   3.任务的执行顺序跟队列有关,串行队列不管同步异步都是顺序执行,并发队列在同步时是顺序执行的
 */
#pragma mark - GCD补充
#pragma mark 群组
- (void)gcdDemo5 {
    /*
     例子:下载若干电影(10份),全部下载完以后,弹出警告框
     先下载电影 ---  下载图片  ---  播放
     */
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    dispatch_group_t group = dispatch_group_create();
   
    //向组中和队列中添加任务
    dispatch_group_async(group, queue, ^{
        [NSThread sleepForTimeInterval:10];
        NSLog(@"下载钢铁侠1");
    });
    dispatch_group_async(group, queue, ^{
        [NSThread sleepForTimeInterval:5];
        NSLog(@"下载钢铁侠2");
    });
    dispatch_group_async(group, queue, ^{
        [NSThread sleepForTimeInterval:2];
        NSLog(@"下载钢铁侠3");
    });
    //当组中的所有任务都执行完毕,会发送一个通知
    dispatch_group_notify(group, queue, ^{
        NSLog(@"钢铁侠系列电影下载完毕");
    });
#pragma mark GCD的内存管理
- (void)gcdDemo6 {
    /*MRC
     1. 凡是通过create创建出来的queue/group都需要release
     create创建出来的东西引用计数为1,通过dispatch_release变为0,系统释放
     2. 对于系统自带的globalQueue,mainQueue,不需要释放
     3. 如果你创建的group/queue作为全局变量来使用的话,需要dispatch_retain
     */
    dispatch_queue_t queue = dispatch_queue_create("myQueue", NULL);
    dispatch_group_t group = dispatch_group_create();
    /*相关操作*/
    /*使用完毕以后记得释放掉*/
    dispatch_release(queue);
    dispatch_release(group);
   
}
#pragma mark GCD的延迟方法
- (void)gcdDemo7 {
    //[self performSelector:<#(SEL)#> withObject:<#(id)#> afterDelay:<#(NSTimeInterval)#>]
   
    /*
     参数2) 单位是纳秒
     */
    dispatch_time_t myTime = dispatch_time(DISPATCH_TIME_NOW, 2*NSEC_PER_SEC);
    dispatch_after(myTime, dispatch_get_main_queue(), ^{
        NSLog(@"延迟后执行这段代码");
    });
}
#pragma mark GCD循环执行某段代码
- (void)gcdDemo8 {
    /*for循环*/
    /*
     参数1)循环次数
     参数2)队列
     参数3)执行的内容
     */
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    /*
     %zu  --->   无符long 类型
     优点:可以同时遍历多个,效率比较高
     缺点:无序的
     */
    dispatch_apply(100, queue, ^(size_t  index) {
        NSLog(@"------%zu----%@",index,[NSThread currentThread]);
    });
   
}
 GCD创建单例类

@implementation People

static People *instance = nil;
+ (instancetype)sharedPeople {
    /*快捷方式:dispatch_onece*/
    /*
     onceToken作为代码只执行一次的标记
     */
    static dispatch_once_t onceToken;
    /*
     需要且必须执行一次的代码块
     好处:如果多个线程同时调用这个方法,那么该函数会"同步等待",直到代码块执行完毕
     */
  
    dispatch_once(&onceToken, ^{
        instance = [[super allocWithZone:NULL] init];
    });
    return instance;
}

+ (id)allocWithZone:(struct _NSZone *)zone {
    return [self sharedPeople];
}

@end
block
 block:块.
     在IOS4.0以后引入的新特性.block是Object-C的”特殊对象”,不是NSObject那种对象
     */
   
    /*
     1. 数组遍历/字典:for   for in     block
     */
    NSArray *array1 = @[@"1",@"2",@"3",@"4"];
    /*
     id obj  --->   数组中的每一个对象,类型为id(可以根据实际情况进行修改)
     NSUInteger idx  --->  数组中对象的索引/编号
     BOOL *stop   --->   break
     */
    [array1 enumerateObjectsUsingBlock:^(NSString *obj, NSUInteger idx, BOOL *stop) {
        NSLog(@"%d -- %@",idx,obj);
        if(idx == 1) {
            *stop = YES;
        }
    }];
    /*
     NSEnumerationConcurrent:并发的
     NSEnumerationReverse:反序
     */
    [array1 enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        NSLog(@"-------   %d -- %@",idx,obj);

}];
   
   
    /*
     id key --> 字典的key
     id obj --> 字典的key所对应的内容
     */
    NSDictionary *dic = nil;
    [dic enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
       
    }];
 /*
     2. UIView动画
     */
    [UIView animateWithDuration:2 animations:^{
        //动画的具体内容:设置控件的终点状态
    }];
   
    [UIView animateWithDuration:2 animations:^{
       
    } completion:^(BOOL finished) {
        //动画完成之后执行的代码写到这里
    }];
   
    //[UIView transitionFromView:<#(UIView *)#> toView:<#(UIView *)#> duration:<#(NSTimeInterval)#> options:<#(UIViewAnimationOptions)#> completion:<#^(BOOL finished)completion#>]
   
   
    /*
     3. 模态
     */
    [self presentViewController:nil animated:YES completion:^{
        //弹出完成后要做的事情
    }];
    [self dismissViewControllerAnimated:YES completion:^{
       //消失之后要做的事情
    }];
   
    /*
     4.发送请求
     */
    [NSURLConnection sendAsynchronousRequest:nil queue:nil completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
       
    }];
   
  5.NSBlockOperation
     */
   
    /*
     6.ASIHttpRequest
     */
    ASIHTTPRequest *request = nil;
    //request.delegate = self;
    [request setCompletionBlock:^{
        //请求完成后的代码
    }];
    [request setFailedBlock:^{
       //请求失败调用的代码
    }];
    [request startAsynchronous];
}
 /*内存管理
     1.内存主要分为五块
     1.1 栈(区):由编译器自动分配/释放,一般用来存放函数的参数值,局部变量的值等.
        例子:int a = 0;
     1.2 堆(区):一般由程序猿分配/释放.如果说程序员不释放,程序结束时可能由OS回收
        例子:People *p = [[People alloc]init];
     1.3 全局区(静态区):全局变量/静态变量放在这个区域.初始化的全局变量/静态变量放在一个区域,未初始化的全局变量/静态变量放在另一个区域.程序结束后由系统释放
     1.4 文字常量区:常量字符串.程序结束后系统释放
         NSString *name=@"张三";
     1.5 程序代码区:存放函数体的二进制代码
    
     2.block本身的内存管理
        2.1 非ARC
          2.1.1
             在非ARC下,block默认分配在"栈区".如果离开block方法的作用域,block会被丢弃/释放
          2.1.2
             NSGlobalBlock(如果块中没有使用外部变量):对于retain,relese,copy无效
             NSStackBlock(如果块中使用了外部变量):retain,release无效,copy有效,会得到NSMallocBlock
                陷阱:如果把block添加到数组中,然后再从数组中取出的block已经被释放了,这个block变成了野指针.正确做法是[array addObject:[[block copy]autorelease]]
             NSMallocBlock(NSStackBlock被copy):支持retain,relese.retain/release可以增加/减少引用计数,但是block的retainCount始终为1.
             建议:不要对block使用retain操作,不方便管理
        2.2 ARC
     3.block块中对象的内存
     前提:主要是针对copy的block
     */

__block int a = 10;
    void(^block1)() = ^() {
        a = 20;
    };
    block1();
    NSLog(@"%@",[block1 copy]);

//陷阱
    int b = 20;
    MyBlock block2 = ^() {
        NSLog(@"%d",b);
    };
    block2();
    NSLog(@"block2:%@",block2);
    NSMutableArray *array = [NSMutableArray array];
    [array addObject:[[block2 copy] autorelease]];
   
    MyBlock block3 = array[0];
    block3();
    NSLog(@"block3:%@",block3);
   
    MyBlock block4 = [block3 retain];
    NSLog(@"----%d",[block3 retainCount]);
   
   
   
   
    __block People * localObj = [People new];
    staticObj        = [People new];
    gloabObj          = [People new];
    _propertyObj      = [People new];
   
    NSLog(@"%d--%d--%d--%d====%d",localObj.retainCount,staticObj.retainCount,gloabObj.retainCount,_propertyObj.retainCount,self.retainCount);
   
    /*block块中的对象
     全局变量:不变
     局部变量:通过block copy会+1 (MRC下局部变量一般需要加上__block,防止循环引用,ARC下加__weak)
     static变量:不变
     属性:不变
    
     self本身也会+1
     */
    MyBlock block5 = ^() {
        gloabObj.age = 10;
        staticObj.age = 20;
        _propertyObj.age = 30;
        localObj.age = 40;
    };
    block5();
    [block5 copy];
    NSLog(@"%d--%d--%d--%d====%d",localObj.retainCount,staticObj.retainCount,gloabObj.retainCount,_propertyObj.retainCount,self.retainCount);
   
}

GCD与block的更多相关文章

  1. GCD code block

    在这里积累一些片段,由于备忘录. + (DRClass *)sharedDR{ //创建小黑.正常ap模式仅仅有一个小黑,so static DRClass *aDR = nil; static di ...

  2. 包建强的培训课程(12):iOS深入学习(内存管理、Block和GCD等)

    @import url(/css/cuteeditor.css); @import url(http://i.cnblogs.com/Load.ashx?type=style&file=Syn ...

  3. block ,GCD(转)

    原文:http://blog.sina.com.cn/s/blog_45e2b66c01010dhd.html 1.GCD之dispatch queue http://www.cnblogs.com/ ...

  4. NSOprationQueue 与 GCD 的区别与选用

    原文链接:http://www.jianshu.com/p/d09e2638eb27 GCD 技术是一个轻量的,底层实现隐藏的神奇技术,我们能够通过GCD和block轻松实现多线程编程,有时候,GCD ...

  5. NSoperation用法详解及与GCD的比较

    NSInvocationOperation // 基于一个对象和selector来创建操作.如果你已经有现有的方法来执行需要的任务,就可以使用这个类 NSInvocationOperation * o ...

  6. GCD 常用代码

    GCD 常用代码 体验代码 异步执行任务 - (void)gcdDemo1 { // 1. 全局队列 dispatch_queue_t q = dispatch_get_global_queue(0, ...

  7. GCD的使用

    什么是 GCD Grand Central Dispatch (GCD) 是 Apple 开发的一个多核编程的解决方法.该方法在 Mac OS X 10.6 雪豹中首次推出,并随后被引入到了 iOS4 ...

  8. iOS进阶面试题----Block部分

    1 什么是block 对于闭包 (block),有很多定义,其中闭包就是能够读取其它函数内部变量的函数,这个定义即接近本质又较好理解.对于刚接触Block的同学,会觉得有些绕, 因为我们习惯写这样的程 ...

  9. 使用GCD

    使用GCD 什么是 GCD Grand Central Dispatch (GCD) 是 Apple 开发的一个多核编程的解决方法.该方法在 Mac OS X 10.6 雪豹中首次推出,并随后被引入到 ...

随机推荐

  1. jqgrid如何在一个页面点击按钮后,传递参数到新页面

    利用 Content/Scripts/dw-framework.js 中的AddTableMenu属性 <div class="Task" style="backg ...

  2. URL编码与解码

    在项目中碰到了ajax传来的参数,后台接收值乱码(如下图)的问题 在此记录一下 前台: 后台: 解决问题 为什么需要编码 怎样编码 实际出现的问题解决方法 1.为什么需要编码? URL 只能使用 AS ...

  3. Win10系统Start Menu上的图标莫名消失

    今天在工作过程中,突然有测试的同事给我报来一个问题.她是这么描述的“执行完XXX工具之后,在Start Menu找不到图标了.” 针对问题本身: 1,是执行完XXXX工具之后? 2,Start Men ...

  4. Dynamics AX 2012 R2 AIF自定义服务中的事务回滚Bug

    Reinhard在一个Customer Service里的一个Method中,发现一个Transcation RollBack Bug.先看该Method的代码: [SysEntryPointAttr ...

  5. 基于tp框架实现的递归城市查询

    控制器层: 接下来就是模型层: 如果说你的数据量庞大到致使apache或者nginx停止运行,有两点原因: 1.代码耦合性不高,代码有错误: 2.php.ini里面有一个memory_limit的这个 ...

  6. MVC系列1-MVC基础

    终于决定写一个系列的文章了,最开始其实是准备写一下WPF的,因为我这两年一直在做WPF,对WPF的喜爱自然是无以言表.但是由于我所在的地区对WPF的普及不是很广泛,所以,被迫又开始做起来web,但是我 ...

  7. asp.net服务控件的生命周期

    1. 初始化 - Init事件 (OnInit 方法)   2. 加载视图状态 - LoadViewState方法   3. 处理回发数据 - LoadPostData方法           对实现 ...

  8. CentOS 安装Zookeeper-3.4.6 单节点

    Dubbo 建议使用 Zookeeper 作为服务的注册中心. 注册中心服务器(192.168.3.71)配置,安装 Zookeeper: 1. 修改操作系统的/etc/hosts 文件中添加: #  ...

  9. [问题2015S03] 复旦高等代数 II(14级)每周一题(第四教学周)

    [问题2015S03]  设 \(g(x)=x^n+a_1x^{n-1}+\cdots+a_{n-1}x+a_n\) 是数域 \(\mathbb{K}\) 上的多项式, \(V\) 是 \(\math ...

  10. wifipineapple使用教程

    1.把开关拨到右边 如果有灯亮说明有电 4个灯全亮说明电量是满的 以此类推 如果一个也不亮说明没电了需要用充电器充电 2.把开关拨到左边打开wifi的开关  会开启一个wifi大概一分钟左右会有wif ...