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

2019-08-04  本文已影响0人  babyloveblues

什么是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];
            
        });
    });

队列的类型

术语梳理

同步 / 异步 / 并发 / 串行

并发队列 & 串行队列

- (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


上一篇下一篇

猜你喜欢

热点阅读