GCD

锁对象:锁对象必须是全局的,还要继承于NSObject;
互斥锁使用线程同步技术;
任务 :决定的是执行的方式,在哪里执行,是在当前的线程执行,还是再开辟一条线程执行;
队列: 决定的是任务的调度方式;决定的是任务怎么执行,是按照顺序还是不按照顺序

GCD:grand central dispatch是苹果公司为多核并行运算提出的方案;自动利用更多的cpu内核,自动管理线程的生命周期
核心:将任务添加到队列; 任务:执行什么操作,一般是block代码,队列:相当于容器,用来存放任务;
步骤:创建队列,创建任务 (确定要做的事情),添加任务到队列;GCD会自动的将队列中的任务取出来,放到对应的线程中执行;
队列的特点:先进先出(FIFO);
NSThread的任务封装在”方法中”;GCD的任务封装在”BLOCK”中;

BLOCK :属于C语言框架
是一种数据类型数据类型 :void (^) ( )
变量名 :void (^myBlock) ( )
赋值 :void (^myBlock) () = ^{ };

是一段代码块,被调用的时候才会执行 (类似于函数和方法);
可以定义为临时变量
可以定义函数
可以定义成属性
本质是函数指针;

block内存arc环境下,定义的单纯的block存储在全局区; <NSGlobalBlock>
访问外部变量,block储存在堆区;访问之前,变量在栈区; 0x7fff
访问时,变量被block拷贝到堆区 0x7fe
访问结束,变量的地址又回到栈区;

修改外部变量:block内部不能修改外部变量,如果修改的话,将外部变量用__Block修饰;
修改之前,变量地址在栈区,在block外面,用__block修饰了,地址不会变
修改时,变量地址跑到了堆区;
修改完成后,变量的地址回不到栈区了,留在了堆区;

MAR下:定义的单纯的block存储在全局区; <NSGlobalBlock>
访问外部变量:访问之前,栈区;
访问时,依然在栈区
访问之后,栈区,但是地址变了,内存空间没有变;

修改外部变量:修改之前,栈区
修改,栈区
修改之后,栈区,而且地址没有变;

block作为属性,MRC要用copy修饰 (ARC下strong也可以),因为要全局共享,所以放在了堆区.

GCD- (void)GCDDemo1{ //1.创建队列 //数据类型 变量名 dispatch_queue_t queue = dispatch_get_global_queue(0, 0); //2.创建任务 : void (^myTask)() = ^{ //代码块中是GCD要执行的任务 NSLog(@"%@",[NSThread currentThread]); }; //3.将任务添加到队列中 dispatch_async(queue, myTask);}
//简写demo1- (void)GCDDemo2{ dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSLog(@"%@",[NSThread currentThread]); });}

pragma mark - GCD实现线程间的通信- (void)GCDDemo3{ dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSLog(@"加载在下载... %@",[NSThread currentThread]); // 下载结束了,回到主线程刷新UI dispatch_async(dispatch_get_main_queue(), ^{ NSLog(@"刷新UI... %@",[NSThread currentThread]); }); });}

串行队列:里面的任务按照顺序依次调度执行,前面一个任务不执行完,后面的任务不会被调度. Serial 同时只能调度一个任务执行;队列的创建:dispatch_queue_t queue = dispatch_queue_create("TT", DISPATCH_QUEUE_SERIAL);

串行➕异步:会开一条心线程,因为是异步,而且mm不会最后打印,循环是有顺序的;- (void)GCDDemo1{ //创建队列 dispatch_queue_t queue = dispatch_queue_create("tt", DISPATCH_QUEUE_SERIAL); for (NSInteger i = 0; i < 10; i++) { //创建任务 void(^task)() = ^{ NSLog(@"%zd %@",i ,[NSThreadcurrentThread]); }; //添加到队列异步 dispatch_async(queue, task); } NSLog(@"mm");}

串行➕同步 :不会开新线程,会在当前的线程执行,mm会最后打印,循环是有顺序的- (void)GCDDemo1{ //创建队列 dispatch_queue_t queue = dispatch_queue_create("tt", DISPATCH_QUEUE_SERIAL); for (NSInteger i = 0; i < 10; i++) { //创建任务 void(^task)() = ^{ NSLog(@"%zd %@",i ,[NSThreadcurrentThread]); }; //添加到队列同步 dispatch_sync(queue, task); } NSLog(@"mm");}

并发队列:可以同时调度多个任务同时执行; Concurrent 自动开启多个线程同时执行多个任务
主队列:专门在主线程上调度任务,不会开启新线程,先进先出的方式,只有主线程空闲时才会调度队列中的任务在主任务执行,如果当前主线程有任务在执行,无论主队列被添加了什么任务,都不会被调度.dispatch_queue_t queue = dispatch_get_main_queue ();

全局队列:效果等同于并发队列;

任务:dispatch_sync (dispatch_queue_t queue ,dispatch_block_t block); 同步方式执行任务,只在当前的线程中依次执行任务;
dispatch_async (dispatch_queue_t queue ,dispatch_block_t block); 异步方式执行任务,新开线程,在新线程中执行任务;

dispatch_after (when ,queue ,block);真的一个异步函数;

同步任务由于是从上到下执行,可以知道具体哪个任务执行完了,但是异步任务顺序不一样,无法知道具体哪个任务完成了;调度组用来监听一组异步任务的状况;dispatch_group_async ();

单例特点:有一个方便外界调用的类方法,用来实例化单例对象;
保证这个类在程序运行的过程中,在内存中有且只有一个实例化对象
保存在内存的静态区(保证单例的生命周期和程序一样长)

缺点:单例保存在静态区,只有在APP死亡时才会结束;
static AudioTool *instance;+ (instancetype)sharedAudioTool{ static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ instance = [[AudioTool alloc] init]; }); return instance;}//由于viewController.m中alloc和shared调用的顺序不一样,所以后面的实现方法里面都重写一下dispatch_once,但是copy是对象copy,所以不用重写+ (instancetype)allocWithZone:(struct _NSZone *)zone{ static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ instance = [super allocWithZone:zone]; }); return instance;}- (id)copyWithZone:(NSZone *)zone{ return instance;}

  • 遍历

    • 下标遍历
    for i in 0..
    • 直接内容遍历
    for s in array {
        print(s) //输出:小明
                 //     中花
                 //     大杨
     }
    
    • enum block遍历下标和内容
     for e in array.enumerated() {
        print("\(e.offset) \(e.element)") //输出:0 小明
                                          //     1 中花
                                          //     2 大杨
     }
    
    • 遍历下标和内容方式二
    for(n, s) in array.enumerated() {
            print("\(n) \(s)")  //输出:0 小明
                                //     1 中花
                             //     2 大杨
    }
    
    • 反序
     for s in array.reversed() {
            print(s) //输出:大杨
                     //     中花
                     //     小明
    }
    
    • 反序索引和内容
    //错的
    for (n, s) in array.reversed().enumerated() {
        print("\(n) \(s)")  //输出:0 大杨
                            //     1 中花
                            //     2 小明
    }
    //对的
    for (n, s) in array.enumerated().reversed() {
        print("\(n) \(s)") //输出:2 大杨
                           //    1 中花
                           //    0 小明
    }
    
- **增**

你可能感兴趣的:(GCD)