美文网首页
iOS基础知识梳理 - 多线程GCD

iOS基础知识梳理 - 多线程GCD

作者: babyloveblues | 来源:发表于2019-08-04 19:51 被阅读0次

    什么是GCD

    • 全称是Grand Central Dispatch(调度)
    • 纯C语言,提供了非常强大的函数

    GCD优势

    • GCD是苹果公司为多核并行运算提出的解决方案
    • GCD会自动利用更多的CPU内核(比如双核、四核)
    • GCD会自动管理线程的生命周期(创建线程、任务调度、销毁线程)
    • 程序员只需要告诉GCD想要执行什么任务,不需要编写任何线程管理代码

    任务和队列

    GCD的两个核心概念

    任务:执行什么操作
    队列:用来存放任务

    GCD使用的两个步骤

    1. 定制任务:确定想做的事情
    2. 将任务添加到队列中:指定运行方式
      -GCD会自动将队列中的任务取出,放到对应的线程执行
      -任务的取出遵循队列的FIFO原则:先进先出,后进后出
      复杂写法
        // 创建任务
        dispatch_block_t task = ^{
            NSLog(@"task %@", [NSThread currentThread]);
        };
    
        // 获取队列
        dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    
        // 把任务放在队列里面
        dispatch_async(queue, task);
    

    简单写法

     dispatch_async(dispatch_get_global_queue(0, 0), ^{
             NSLog(@"task %@", [NSThread currentThread]);
        });
    

    示例 - 使用GCD异步下载图片

    dispatch_async(dispatch_get_global_queue(0, 0), ^{
            
            NSString *str = @"https://desk-fd.zol-img.com.cn/t_s1280x800c5/g5/M00/02/04/ChMkJ1bKx4qIGTZLAAmjEID8lj0AALH1ADgWvsACaMo983.jpg";
            NSURL *url = [NSURL URLWithString:str];
            // 获取图片资源
            NSData *data = [NSData dataWithContentsOfURL:url];
            
            // 闭包
            UIImage *img = [UIImage imageWithData:data];
            
            // 线程通信
            dispatch_async(dispatch_get_main_queue(), ^{
                
                self.imgV.image = img;
                // 根据图片的大小显示图片
                [self.imgV sizeToFit];
                [self.scrlView setContentSize:img.size];
                
            });
        });
    

    队列的类型

    • 并发队列(Concurrent Dispatch Queue)
      1. 可依然多个任务并发(同时)执行(自动开启多个线程被执行任务)
        2.并发功能只有在异步(dispatch_async)函数下才有效
    • 串行队列(Serial Dispatch Queue)
      1. 让任务一个接着一个的执行(一个执行玩了之后再执行下一个任务)
    • 主队列
      特殊的串行队列,代表主线程

    术语梳理

    同步 / 异步 / 并发 / 串行

    • 同步和异步决定了要不要开启新线程
      同步:在当前线程中执行任务,不具备开启新线程的能力
      异步:在新的线程中执行任务,具备开启新线程的能力
    • 并发和串行决定了任务的执行方式
      并发:多个任务并发(同时)执行
      串行:一个任务执行完毕后,再执行下一个任务
      // 串行队列,同步执行
      // 不开线程,在当前线程下执行

    并发队列 & 串行队列

    - (void)demo1{
        // 创建串行队列
        // 参数一:给队列起个名字
        // 参数二:队列的属性
        
        
        dispatch_queue_t serialQueue = dispatch_queue_create("serialQueue", DISPATCH_QUEUE_SERIAL);
        for (int i = 0; i < 20; i++) {
            dispatch_sync(serialQueue, ^{
                
                NSLog(@"serialQueue %@", [NSThread currentThread]);
                
            });
        }
        
        
    }
    
    // 串行队列,异步执行
    // 开一个线程,任务是有序执行的
    - (void)demo2{
        // 创建串行队列
        // 参数一:给队列起个名字
        // 参数二:队列的属性
        
        dispatch_queue_t serialQueue = dispatch_queue_create("serialQueue", DISPATCH_QUEUE_SERIAL);
        
        for (int i = 0; i < 20; i++) {
            
            dispatch_async(serialQueue, ^{
                
                NSLog(@"serialQueue %@", [NSThread currentThread]);
                
            });
            
        }
        
    }
    
    // 并行队列 异步执行
    // 开多个线程
    // 任务无序执行
    - (void)demo3{
        // 创建串行队列
        // 参数一:给队列起个名字
        // 参数二:队列的属性
        
        
        dispatch_queue_t concurrentQueue = dispatch_queue_create("concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
        for (int i = 0; i < 20; i++) {
            dispatch_async(concurrentQueue, ^{
                
                NSLog(@"serialQueue %@", [NSThread currentThread]);
                
            });
        }
        
    }
    
    // 并行队列 同步执行
    // 不开线程,在当前线程下执行
    // 任务顺序执行
    // 等于串行同步执行
    - (void)demo4{
        // 创建串行队列
        // 参数一:给队列起个名字
        // 参数二:队列的属性
        dispatch_queue_t concurrentQueue = dispatch_queue_create("concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
        for (int i = 0; i < 20; i++) {
            dispatch_sync(concurrentQueue, ^{
                
                NSLog(@"serialQueue %@", [NSThread currentThread]);
                
            });
        }
        
    }
    
    串行 并行

    主队列

    // 主队列异步执行
    -(void)demo1{
        // 得到主队列
        dispatch_queue_t mainQueue = dispatch_get_main_queue();
        
        for (int i = 0; i < 20; i++) {
            dispatch_async(mainQueue, ^{
                
                NSLog(@"MAIN QUEUE %@ %d", [NSThread currentThread], i);
                
            });
        }
        
    }
    
    // 主队列同步执行
    // 这种情况是死锁的,是错的!!!!!!!!!!
    // 死锁:主线程下,望住队列添加任务并且同步执行
    -(void)demo2{
        
        NSLog(@"begin");
        // 得到主队列
        dispatch_queue_t mainQueue = dispatch_get_main_queue();
        
        dispatch_sync(mainQueue, ^{
            NSLog(@"MAIN QUEUE %@", [NSThread currentThread]);
        });
        NSLog(@"end");
    }
    

    对照表

    对照表

    同步执行实战

    延时执行

    使用GCD的好处就是计时精度高

    - (void)demo1{
        
    //    // 方式1 timer
    //    NSTimer *timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(task) userInfo:nil repeats:NO];
    //
    //    //方式2
    //    [self performSelector:@selector(task) withObject:nil afterDelay:1];
    //
        // 参数1:延迟的时间 dispatch_time生成时间(以纳秒做单位 精度高)
        // 参数2:队列
        // 参数3:任务
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        
            NSLog(@"task");
            
        });
        
        NSLog(@"over");
        
    }
    

    队列组

    使用队列组下载两个zip文件

    - (void)demo1{
        
        NSLog(@"begin");
        // 创建队列组
        dispatch_group_t group = dispatch_group_create();
    
        dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
            
            [NSThread sleepForTimeInterval:arc4random_uniform(5)];
            NSLog(@"LOL1.zip %@", [NSThread currentThread]);
            
        });
        
        
        dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
            
            [NSThread sleepForTimeInterval:arc4random_uniform(5)];
            NSLog(@"LOL2.zip %@", [NSThread currentThread]);
            
        });
        
        dispatch_group_notify(group, dispatch_get_main_queue(), ^{
            
            NSLog(@"所有任务都下载完成%@", [NSThread currentThread]);
            
        });
    }
    

    打开终端Terminal键入man dispatch_group_async


    相关文章

      网友评论

          本文标题:iOS基础知识梳理 - 多线程GCD

          本文链接:https://www.haomeiwen.com/subject/lblydctx.html