iOS多线程开发————GCD的基本使用

在此小编做一个自我学习的总结和对iOS开发新新人的小小福利吧。


直奔主题的吧,讲讲GCD:Grand Central Dispatch(多线程优化技术),是Apple提供的一套更底层,更高效的并发编程技术,属于纯C语言编写,基于Block实现的,支持同步或者异步任务处理,串行或并行的处理队列,非系统调用的信号量机制,定时任务处理、进程、文件或者网络监听任务等。特别的:GCD可以自动的根据系统负载来增减线程数量,同时也无需加锁或其他同步机制。


GCD的常用属性及方法:

Dispatch Queue(执行处理的等待队列),它包含Serial Dispatch Queue(串行队列)和 Concurrent Dispatch Queue(并发队列)

Serial Dispatch Queue:(串行队列)等待当前正在执行的任务结束再处理下一个任务,一个线程同时执行一个任务,避免数据的竞争,可以生成多个Serial Dispatch Queue 并行执行。

Concurrent Dispatch Queue:(并发队列)不等待当前正在执行的任务结束便处理下一个任务,多个线程同时执行多个任务,具体有多少线程根据CPU核数和其负载来决定。

Main Dispatch Queue:(主队列),在主线程中执行的队列,因为主线程只有一个,因此Main Dispatch Queue就是Serial Dispatch Queue。一切跟UI有关的操作必须放在主队列中。

Global Dispatch Queue:(全局队列),它是所有应用程序都能使用的Concurrent Dispatch Queue。他也是并发队列的一种,可看做系统创建的并发队列。

同步:sync,任务串行执行。

异步:async,任务并行执行。

注意:

 添加同步任务,无论是串行还是并行都不会开启多线程,都在当前线程中执行,运行完毕后才会执行下面的代码。

 添加异步任务到串行队列有可能会开启多线程。

 添加异步任务到全局队列会开启多线程,所添加的任务并发执行。

实例:添加同步任务到串行队列


//同步添加到串行队列
- (void)addTaskSerialQueueForSync {
    
    //创建一个串行队列
    dispatch_queue_t serialQueue = dispatch_queue_create("serialQueue", DISPATCH_QUEUE_SERIAL);
    
    //添加同步任务1
    //将任务1 同步添加到串行队列中去
    dispatch_sync(serialQueue, ^{
    
        for (int i = 0; i < 10; i++) {
            NSLog(@"任务1:%i", i);
        }
    });
    NSLog(@"任务1执行完毕");
    
    //添加同步任务2
    //将任务2 同步添加到串行队列中去
    dispatch_sync(serialQueue, ^{
        
        for (int i = 0; i < 10; i++) {
            NSLog(@"任务2:%i", i);
        }
    });
    NSLog(@"任务2执行完毕");
    
    /*
     执行结果:先添加任务1,执行完毕后添加任务2并执行完毕
     */
}

实例:添加同步任务到并行队列

//同步添加到并发队列
- (void)addTaskConcurrentQueueForSync {
    
    //创建并发队列
    //普通的并发队列
//    dispatch_queue_t queue = dispatch_queue_create("concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
    
    //全局队列
    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    //添加同步任务3
    //将任务3 同步添加到串行队列中去
    dispatch_sync(globalQueue, ^{
        
        for (int i = 0; i < 10; i++) {
            NSLog(@"任务3:%i", i);
        }
    });
    NSLog(@"任务3执行完毕");
    
    //添加同步任务4
    //将任务4 同步添加到串行队列中去
    dispatch_sync(globalQueue, ^{
    
        for (int i = 0; i < 10; i++) {
            NSLog(@"任务4:%i", i);
        }
    });
    NSLog(@"任务4执行完毕");
    
    /*
     执行结果:先添加任务3,执行完毕后添加任务4并执行完毕
     */
}

实例:添加异步任务到串行队列

//异步添加到串行队列
- (void)addTaskSerialQueueForAsync {
    
    //创建串行队列
    dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);
    
    //将任务5 异步添加到串行队列中去
    dispatch_async(queue, ^{
    
        for (int i = 0; i < 10; i++) {
            NSLog(@"任务5:%i", i);
        }
    });
    NSLog(@"任务5添加完毕");
    
    //将任务6 异步添加到串行队列中去
    dispatch_async(queue, ^{
        
        for (int i = 0; i < 10; i++) {
            NSLog(@"任务6:%i", i);
        }
    });
    NSLog(@"任务6添加完毕");
    
    /*
     执行结果:先添加完成任务5,马上开始执行任务5,还未执行完毕时有添加完成了任务6,当任务5执行完之后才会执行任务6(因为是串行队列)
     */
}


实例:添加异步任务到并行队列

//异步添加到并发队列
- (void)addTaskConcurrentQueueForAsync {
    
    //全局队列
    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    //将任务7 异步添加到串行队列中去
    dispatch_async(globalQueue, ^{
        
        for (int i = 0; i < 10; i++) {
            NSLog(@"任务7:%i", i);
        }
    });
    NSLog(@"任务7添加完毕");
    
    //将任务8 异步添加到串行队列中去
    dispatch_async(globalQueue, ^{
        
        for (int i = 0; i < 10; i++) {
            NSLog(@"任务8:%i", i);
        }
    });
    NSLog(@"任务8添加完毕");
    
    /*
     执行结果:先添加任务7,立刻开始执行任务7,随后立刻添加完成任务8(此时任务7并没有执行完),这时任务7与任务8同时执行。
     */
}


总结:

 1. 创建队列dispatch_queue_create()      获取全局队列,主队列

 2. 同步添加任务: 需要等待任务s的执行,才能继续运行

 3. 异步添加任务: 无需等待任务的执行,能过直接运行下面的代码


GCD的一些其他方法

延迟任务:dispatch _after:等待指定的时间后,异步添加到一个block块到指定的队列里面,不堵塞当前的线程。

- (void)delay {
    
    
    //创建调用时机
    //参数1:参照时间,基础时间
    //参数2:延迟时间,以纳秒为单位的整数
    dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 5);
    
    /**
     *  延迟调用
     *
     *  @param when    调用的时间
     *  @param queue   所在的队列
     *  @param void    调用的任务
     *
     */
    dispatch_after(time, dispatch_get_main_queue(), ^{
        NSLog(@"延迟5秒后调用的任务");
    });
    NSLog(@"延迟任务 添加完毕");
    
    /*
     执行结果:先添加延迟任务完毕,经过5秒后执行完打印“延迟5秒后调用的任务”
     */
    
    //其他延时调用的方法
    // [self performSelector:<#(nonnull SEL)#> withObject:<#(nullable id)#> afterDelay:<#(NSTimeInterval)#>];
    
    // [NSObject cancelPreviousPerformRequestsWithTarget:<#(nonnull id)#>];
    
}

设置队列优先级:dispatch_set_target_queue:改变queue的优先级与目标queue一致,可以使多个serial queue在目标queue上执行,一次只有一个任务执行(串行)。 挂起任务:dispatch_suspend:暂停队列里面尚未开始执行的任务,对已经开始执行的任务没有影响。

queue 的 suspend reference count + 1。

恢复任务:dispatch_resume:恢复队列中被挂起的任务,使这些任务能够继续执行

queue 的 suspend reference count - 1

注意:必须平衡使用suspend和resume。

组任务:

dispatch_group_async:监视一组block任务的完成,多个任务都结束后的一个汇总处理。

dispatch_group_notify:所有任务执行完成后汇总,不阻塞当前线程。

dispatch_group_wait:等待直到所有任务执行结束,中途不能取消,阻塞当前线程。

- (void)groupTask {
    
    //创建队列
    dispatch_queue_t global = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    //创建一个任务组
    dispatch_group_t group = dispatch_group_create();
    
    //向任务组中 添加任务
    dispatch_group_async(group, global, ^{
        
        NSLog(@"任务1 开始");
        [NSThread sleepForTimeInterval: 2];
        NSLog(@"任务1 结束");
    });
    
    dispatch_group_async(group, global, ^{
       
        NSLog(@"任务2 开始");
        [NSThread sleepForTimeInterval:3];
        NSLog(@"任务2 结束");
    });
    
    dispatch_group_async(group, global, ^{
        
        NSLog(@"任务3 开始");
        [NSThread sleepForTimeInterval:15];
        NSLog(@"任务3 结束");
    });
    
    //任务汇总回调
    dispatch_group_notify(group, global, ^{
       
        NSLog(@"所有任务 已完成!");
    });
    
    //在任务开始5秒后,来查看任务的执行情况
    dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC);
    
    //等待直到某一时刻,然后去查看任务组中任务的完成情况
    //等待操作,会阻塞线程
    long  result = dispatch_group_wait(group, time);
    
    //当time = DISPATCH_TIME_FOREVER 时代表永久等待,直到任务完成
//    long  result = dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    
    if (result == 0) {
        NSLog(@"所有任务执行成功");
    } else {
        NSLog(@"某些任务没有执行完毕");
    }
    
    /*
     执行结果:任务123依次添加到任务组中去执行,因为任务3休眠时间较长,而等待操作只有5秒,因此会检测到有任务没有执行完毕,等15秒过后,notif执行所有任务已经执行完成的通知。
     */
}


你可能感兴趣的:(多线程,ios开发)