美文网首页
使用 GCD 控制线程执行顺序

使用 GCD 控制线程执行顺序

作者: AprSnow | 来源:发表于2018-08-21 17:53 被阅读140次

前言

需求:有三个异步执行的任务ABC任务 C 必须等待任务 A任务 B 执行完毕才执行。

本文分别采用三种方法来实现线程执行顺序的控制,semaphorebarriergroup。详细代码可以参考 WZHWaitThread

Semaphore

执行 dispatch_semaphore_wait 时,如果信号量大于 0,可以继续执行并把信号量减一;如果信号量小于等于 0,线程被阻塞,等待信号量大于 0dispatch_semaphore_signal 释放信号量,使信号量加一。dispatch_semaphore_waitdispatch_semaphore_signal 配合使用可以控制线程的执行。

- (void)waitThreadWithSemaphore {
    dispatch_queue_t currentQueue = dispatch_queue_create("current queue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(2);
    
    dispatch_async(currentQueue, ^{
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        NSLog(@"Thread A %@", [NSThread currentThread]);
        dispatch_semaphore_signal(semaphore);
    });

    dispatch_async(currentQueue, ^{
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        NSLog(@"Thread B %@", [NSThread currentThread]);
        dispatch_semaphore_signal(semaphore);
    });

    dispatch_async(currentQueue, ^{
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        NSLog(@"Thread C %@", [NSThread currentThread]);
        dispatch_semaphore_signal(semaphore);
        dispatch_semaphore_signal(semaphore);
        // dispatch_semaphore_wait 和 dispatch_semaphore_signal 必须成对使用
    });
    
    NSLog(@"Wait Thread Test.");
}

Barrier

dispatch_barrier_async 可以拦截线程的执行,在 dispatch_barrier_async 之前的线程执行完才会执行 dispatch_barrier_async 之后的的线程。这里注意两点:

  1. 在使用栅栏函数时,使用自定义的并行队列才有意义,如果用的是串行队列或者系统提供的全局并发队列,这个栅栏函数的作用等同于一个 dispatch_sync 的作用。

The queue you specify should be a concurrent queue that you create yourself using the dispatch_queue_create function. If the queue you pass to this function is a serial queue or one of the global concurrent queues, this function behaves like the dispatch_sync function.

  1. dispatch_barrier_asyncdispatch_barrier_sync 的区别

dispatch_barrier_sync 需要等待自己的任务结束之后才会继续程序,然后执行后面的任务;
dispatch_barrier_async 将自己的任务插入到 queue 之后,不会等待自己的任务结束,会继续把后面的任务插入到 queue

- (void)waitThreadWithBarrier {
    dispatch_queue_t queue = dispatch_queue_create("current queue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
        NSLog(@"Thread A %@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"Thread B %@", [NSThread currentThread]);
    });
    
    dispatch_barrier_sync(queue, ^{
        NSLog(@"barrier %@", [NSThread currentThread]);
    });

    dispatch_async(queue, ^{
        NSLog(@"Thread C %@", [NSThread currentThread]);
    });
    
    NSLog(@"Wait Thread Test In %@", [NSThread currentThread]);
}

Group

dispatch_group 可以把相关的任务归并到一个组内来执行,通过监听组内所有任务的执行情况来做相应处理。待任务组执行完毕时调用 dispatch_group_notify,不会阻塞当前线程。或者 dispatch_group_wait 可以等待组任务完成,会阻塞当前线程,当任务组执行完毕时,才会解除阻塞当前线程。

注意:不要在主线程使用 dispatch_group_wait,如果 group 中如果添加主队列后再使用 dispatch_group_wait 有可能引起死锁。

- (void)waitThreadWithGroup {
    dispatch_queue_t queue = dispatch_queue_create("current queue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_async(group, queue, ^{
        NSLog(@"Thread A %@", [NSThread currentThread]);
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"Thread B %@", [NSThread currentThread]);
    });
    dispatch_group_notify(group, queue, ^{
        NSLog(@"Thread C %@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
        NSLog(@"Wait Thread Test In %@", [NSThread currentThread]);
    });
}

相关文章

  • GCD

    GCD线程执行的顺序控制 dispatch_group_t group = dispatch_group_crea...

  • 使用 GCD 控制线程执行顺序

    前言 需求:有三个异步执行的任务A、B、C,任务 C 必须等待任务 A 和 任务 B 执行完毕才执行。 本文分别采...

  • 多线程二

    GCD 栅栏函数 dispatch_barrier_async 控制任务执行顺序,同步 保证线程安全 栅栏函数只能...

  • iOS GCD扩展用法

    GCD 延迟执行 GCD 一次性代码 栅栏函数(控制任务的执行顺序) 其他 补充 使用Crearte函数创建的并发...

  • iOS多线程-并发队列

    GCD 并发队列 并发队列,异步执行 问题:1.会开几条线程?会开多条线程,线程数量是由GCD来决定2.会顺序执行...

  • GCD其它常用函数(四)

    一. 延迟执行 iOS常见的延时执行调用NSObject的方法 使用GCD函数(延迟并控制方法在哪个线程执行) 使...

  • iOS 中线程与队列的关系

    主线程主队列? 结论:GCD的主线程任务总会再最后执行。除GCD外的任务顺序执行。原因呢? 主线程是只有一个主队列...

  • 多线程之GCD栅栏函数,GCD快速迭代,队列组

    1. GCD栅栏函数 作用:只有当栅栏函数执行完毕后才能执行后面的函数 需求:使用栅栏函数规定线程执行顺序 注意点...

  • 谈谈对多线程和GCD的理解

    多线程(GCD) GCD是异步执行任务的技术之一,通过Dispatch Queue来控制任务的执行,线程管理由系统...

  • 线程基础

    线程与进程 线程:进程中负责程序执行的执行单元,线程本身依靠程序进行运行,线程是程序中的顺序控制流,只能使用分配给...

网友评论

      本文标题:使用 GCD 控制线程执行顺序

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