GCD

  • sizeTOfit:如果让一个label和文字一样大,可以用,如果让一个imageVIew和图片一样大,可以用。

  • 无符号整数:%tu NSUintrger 有符号整数:%zd NSInteger。可以适应程序CPU架构。32,64位都不会出错。

  • loadView方法目的就是创建view,如果view等于空,会重复调用这个方法。

    (1)GCD:针对多核处理器提供的解决方案。把任务添加到队列,并且执行指定的任务函数,任务都由Block封装(既没参数也没返回值的Block)。是一个并发技术,已经没有线程的感觉了。底层安排是自动实现的,线程池维护的。

    (2)同步&异步(任务):

        1.同步(sync):前面执行完毕执行下一句。保证原有的代码执行顺序。不管并发还是串行,同步在就是顺序执行。

                作用:

        2.异步(async):不用等直接执行。异步是多线程的代名词。

    (3)GCD原理:任务添加到队列。任务就是Block,队列就是主队列,全局队列啊。然后选择同步异步(sync,async)。GCD会管理线程生命周期。所以看不到线程的感觉。GCD底层会有一个线程池。把任务添加到队列后,队列负责调度执行。队列回去找线程池要可用的线程,然后把任务放到线程,执行完毕后线程空闲,就会回收到线程池。然后如果没人用了,就释放了。像NSThread的detahch和perform,每次添加任务都会增加线程,234567持续。想要做一个线程池不容易。而GCD会自动回收,底层线程池会做一个复用,234555555555.

// 线程间通讯
- (void)gcdDemo3 {
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"玩命下载中...%@", [NSThread currentThread]);
        
        // 更新UI
        dispatch_sync(dispatch_get_main_queue(), ^{
            NSLog(@"更新UI %@", [NSThread currentThread]);
        });
    });
}

5)队列:从数据结构上讲,先进先出。

        1.串行队列:不管同步异步,前面不执行完就不调度后面的。只会开启一条线程。     

dispatch_queue_t queue = dispatch_queue_create("MY", DISPATCH_QUEUE_SERIAL);

        2.并发队列:

 

dispatch_queue_t queuee = dispatch_queue_create("MY", DISPATCH_QUEUE_CONCURRENT);

        总结:开不开线程由函数决定。同步不开异步开。

                 (异步)开多少线程由队列决定。串行最多一条,并发由底层线程池决定。

                 线程不是越多越好。IOS7.0使用GCD只能开5-6条。8.0就能开很多。

                 因为苹果建议大家用NSOperation(OC的),对GCD的封装。

                 因为GCD还给排列组合。GCD是底层C语言的。

    (6)主队列同步&异步:主队列是专门用来在主线程调入任务的。先进先出。必须主线程控线才能调度任务。随着程序启动就创建好了。主线程异步演练结果就是必须等主线程全部完成才执行异步。主队列同步时候会出现互相等的现象,俗称死锁。你等我我等你。(也有不死锁时候)。

    (7)主队列同步不死锁:

(8)同步作用:不开线程,不执行完不会调度后续的任务。

- (void)mydemo1 {
    
    // 所有耗时操作都是异步
    // 同步任务不完成,队列后面的异步也不能执行
    dispatch_queue_t queue = dispatch_queue_create("MY", DISPATCH_QUEUE_CONCURRENT);
    
    void (^tast)() = ^ {
        
      dispatch_sync(queue, ^{
          NSLog(@"login%@",[NSThread currentThread]);
      });
        
      dispatch_sync(queue, ^{
          NSLog(@"download A%@",[NSThread currentThread]);
      });
        
      dispatch_sync(queue, ^{
          NSLog(@"download B%@",[NSThread currentThread]);
      });
        
    };
    
    dispatch_async(queue, tast);
    
}

 (9)全局队列:

 

/**

    * 全局队列和并发对列的工作特性一致

    * ARC 不允许使用 dispatch_release

      但是 MRC 就必须要用 dispatch_release(q);

    * 全局队列更方便

    * 通常开发复杂的网络应用,第三方框架时,才需要使用自定义并发队列!

 */

    // 1. 全局队列

    // 第1个参数也用0 - 可以保证 iOS 7.0 & 8.0 的适配

    // 第2个参数是 0

 

(10)barrier阻塞:NSMutableArray是线程不安全的,多个线程添加数组有可能会抢,会崩溃。XCODE7自行测试是数组数量不够。10个可能只有七个,还不会崩溃。添加barrier就好了。barrier是把所有异步执行完毕后,在同一个线程顺序执行自己的block。barrier可以卡在异步 barrier 异步中。先执行全部异步,在阻塞统一barrier,在进行下面的异步。而且用的时候必须用自定义的队列。而不是全部队列,全局队列会失效。最主要应用:数据存储IO,下载一堆东西,需要顺序安全输出。

 dispatch_barrier_async(_queue, ^{
            [self.myarray addObject:image];
            NSLog(@"添加完成%@--%@",filename,[NSThread currentThread]);
            
        });

(11)一次性执行:dispatch_once (单例)如果要保证对象只被实例化一次,就要放到静态区。因为block内部想要修改外部的变量,第一反应是用__block,但是当onceToken = 0时候还可以,当单例执行了一次后,出了代码块就消失了,盛夏时候onceToken != 0就无法,此时对象永远都为nil。所以用static来修饰。并且dispatch_once是同步的。是线程安全的。内部也有一把锁,性能很高。

(12)调度组:在一组异步代码执行完毕后,统一获得通知。类似barrier。

              应用场景:加载20条微博,缓存所有图片,拿到本地后知道图片的宽高(网络都是二进制数据),将一组图像异步缓存到本地之后统一获得通知。

              调度组一点也没有改变原有的GCD,只是在任务开始时候,进组(加一个标记),然后block最后一句离组。当组没东西就可以发通知了。

 

- (void)group2 {
    // 队列
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    // 调度组
    dispatch_group_t group = dispatch_group_create();
    
    // 1. 进入群组,给 group 打一个标记,在后续紧接着的 block 归 group 监听
    // dispatch_group_enter 和 dispatch_group_leave 必须成对出现!
    dispatch_group_enter(group);
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:0.8];
        NSLog(@"download A - %@", [NSThread currentThread]);
        // 耗时操作....
        
        // block 的最后一句
        // 2. 离开群组
        dispatch_group_leave(group);
    });
    
    dispatch_group_enter(group);
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:1.0];
        NSLog(@"download B - %@", [NSThread currentThread]);
        // 耗时操作....
        
        // block 的最后一句
        // 2. 离开群组
        dispatch_group_leave(group);
    });
    
    // 监听群组完成 dispatch_group_notify - 异步的
//    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
//        NSLog(@"OK");
//    });
    // 等待群组空,一直到永远,群组不空,这句代码就死等,同步
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    NSLog(@"OK");
}
    (13)延迟操作:dispatch_after
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"hey");
    });

 

posted @ 2016-08-25 15:46  三更小新  阅读(108)  评论(0编辑  收藏  举报