iOS-多线程之GCD

在说GCD之前,先说几个核心的概念

任务:执行什么操作
队列:用来存放任务
1 - 并发队列(Concurrent Dispatch Queue)
   可以让多个任务并发(同时)执行(自动开启多个线程同时执行任务)
   并发功能只有在异步(dispatch_async)函数下才有效

2 - 串行队列(Serial Dispatch Queue)
   让任务一个接着一个地执行(一个任务执行完毕后,再执行下一个任务)

同步和异步的区别

同步:只能在当前线程中执行任务,不具备开启新线程的能力
异步:可以在新的线程中执行任务,具备开启新线程的能力

GCD使用步骤

一、创建任务

二、将任务添加到队列中
GCD会自动将队列中的任务取出,放到对应的线程中执行
任务的取出遵循队列的FIFO原则:先进先出,后进后出

GCD线程队列的创建方法

1、创建一个串行队列

    /** * 创建一个串行队列 * *  @param "Mazy" 队列的标示符 *  @param DISPATCH_QUEUE_SERIAL 串行队列 DISPATCH_QUEUE_CONCURRENT 并发队列 * *  @return 返回串行队列 */
    dispatch_queue_t serialQueue = dispatch_queue_create("Mazy", DISPATCH_QUEUE_SERIAL);

2、创建一个并发队列

/** * 创建一个并发队列 * *  @param "Mazy" 队列的标示符 *  @param DISPATCH_QUEUE_CONCURRENT 并发队列 * *  @return 返回并发队列 */
    dispatch_queue_t concurrentQueue = dispatch_queue_create("Mazy", DISPATCH_QUEUE_CONCURRENT);

3、获得全局并发队列

/** * 获得全局并发队列 * *  @param DISPATCH_QUEUE_PRIORITY_DEFAULT 线程队列的优先级 DISPATCH_QUEUE_PRIORITY_HIGH 2 高 DISPATCH_QUEUE_PRIORITY_DEFAULT 0 一般 默认 DISPATCH_QUEUE_PRIORITY_LOW (-2) 低 DISPATCH_QUEUE_PRIORITY_BACKGROUND 很低 *  @param 0 系统保留参数 * *  @return 返回全局并发队列 */
    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

3、获得主队列

/** * 获得主队列 * *  @return 返回主线程队列 */
    dispatch_queue_t mainQueue = dispatch_get_main_queue();

同步/异步 + 串行/并发队列的组合

1、同步 + 串行队列

// 同步 + 串行队列:不会开启新的线程,在当前线程执行任务。任务是串行的,执行完一个任务,再执行下一个任务
-(void)sync_serial {
    // 创建一个串行队列
    dispatch_queue_t queue = dispatch_queue_create("Mazy", DISPATCH_QUEUE_SERIAL);
    // 同步执行三个任务
    dispatch_sync(queue, ^{
        NSLog(@"1 %@",[NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"2 %@",[NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"3 %@",[NSThread currentThread]);
    });
}

打印结果:
这里写图片描述
总结:没有创建新线程,主线程执行任务,任务串行执行

2、异步 + 串行队列

// 异步 + 串行队列:开启新的线程,但只开启一条
-(void)async_serial {
    // 创建一个串行队列
    dispatch_queue_t queue = dispatch_queue_create("Mazy", DISPATCH_QUEUE_SERIAL);
    // 异步执行三个任务
    dispatch_async(queue, ^{
        NSLog(@"1 %@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"2 %@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"3 %@",[NSThread currentThread]);
    });
}

打印结果:
这里写图片描述
总结:开启了一条线程,任务串行执行

3、同步 + 并发队列

// 同步 + 并发队列:不会开启新的线程
-(void)sync_concurrent {
    // 创建一个全局并发队列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    // 同步执行三个任务
    dispatch_sync(queue, ^{
        NSLog(@"1 %@",[NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"2 %@",[NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"3 %@",[NSThread currentThread]);
    });
}

打印结果:
这里写图片描述
总结:不开启新线程,主线程执行任务,任务也是顺序执行

4、异步 + 并发队列

// 异步 + 并发队列:同时开启多条线程
-(void)async_concurrent {
    // 创建一个全局并发队列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    // 异步执行三个任务
    dispatch_async(queue, ^{
        NSLog(@"1 %@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"2 %@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"3 %@",[NSThread currentThread]);
    });
}

打印结果:
这里写图片描述
总结:开启多条线程,并发执行任务

GCD线程之间的通信

从子线程回到主线程

从子线程回到主线程
dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // 执行耗时的异步操作...
      dispatch_async(dispatch_get_main_queue(), ^{
        // 回到主线程,执行UI刷新操作
        });
});

线程之间的通信具体实现实例

    // 创建 异步 全局并发队列
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // 图片的网络路径
        NSURL *url = [NSURL URLWithString:@"http://xxx.jpg"];

        // 加载图片
        NSData *data = [NSData dataWithContentsOfURL:url];

        // 生成图片
        UIImage *image = [UIImage imageWithData:data];

        // 回到主线程设置图片
        dispatch_async(dispatch_get_main_queue(), ^{
            self.imageView.image = image;
        });
    });

GCD的其他使用

延迟执行

/** * 延迟执行 */
-(void)delay {
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"---我被延迟了3秒执行---");
    });
}

其他延迟执行方法

// method 1
[self performSelector:@selector(do_method) withObject:nil afterDelay:3.0];

// method 2
[NSTimer scheduledTimerWithTimeInterval:3.0 target:self selector:@selector(do_method) userInfo:nil repeats:NO];

只执行一次(用于实现单例模式)

/** * 只执行一次 */
-(void)onlyOnce {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSLog(@"---我只会被执行一次---");
    });
}

快速遍历

/** * 快速遍历 */
-(void)apply {
   // 创建一个全局并发队列
   dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    NSInteger count = 10;
    dispatch_apply(count, queue, ^(size_t index) {
        NSLog(@"%zd--%@",index,[NSThread currentThread]);
    });
}

打印结果:
iOS-多线程之GCD_第1张图片
总结:开启多条线程执行任务,速度远比(for…in…) 遍历快,对于无序的遍历,此方法比较合适

创建线程群组
例如同一个文件分段下载,待所有分段任务下载完成后,合并任务

/** * 创建线程群组 */
-(void)group {
    // 创建一个全局并发队列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    // 创建一个队列组
    dispatch_group_t group = dispatch_group_create();

    dispatch_group_async(group, queue, ^{
        NSLog(@"我是任务-1 %@",[NSThread currentThread]);
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"我是任务-2 %@",[NSThread currentThread]);
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"我是任务-3 %@",[NSThread currentThread]);
    });

    // 待群组中的每个任务执行完成后,执行此方法
    dispatch_group_notify(group, queue, ^{
        NSLog(@"我是终极任务,只有在group里面的任务执行完毕后才执行");
        NSLog(@"%@",[NSThread currentThread]);

    });
}

打印结果:

总结:开启多条线程,去执行群组中的任务,当群组内的三个任务执行完毕后,再去执行notify里面的任务

创建屏障线程队列

/** * 创建屏障线程队列 */
-(void)barrier {
    // 创建一个并发队列
    dispatch_queue_t queue = dispatch_queue_create("Mazy", DISPATCH_QUEUE_CONCURRENT);
    // 创建四个异步任务
    dispatch_async(queue, ^{
        NSLog(@"我是任务-1 %@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"我是任务-2 %@",[NSThread currentThread]);
    });

    // 创建屏障线程队列
    dispatch_barrier_async(queue, ^{
        NSLog(@"----barrier-----%@", [NSThread currentThread]);
    });

    dispatch_async(queue, ^{
        NSLog(@"我是任务-3 %@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"我是任务-4 %@",[NSThread currentThread]);
    });
}

打印结果:
iOS-多线程之GCD_第2张图片
总结:会优先执行屏障前面的任务,当屏障前的所有任务执行完毕后,再去执行后面的任务

注意:使用sync同步函数往当前串行队列中添加任务,会卡住当前的串行队列

你可能感兴趣的:(多线程,并发,同步,异步,gcd)