iOS-多线程编程学习之GCD——线程组、延时、计时器等(六)

上一篇文章我们介绍了GCD,以及其队列,同步异步等概念。这次我们将探讨更多GCD的功能,包括线程组(group),栅栏(barrier),单例(once),延时(after),并发迭代(apply)和计时器(timer)。

再有了上一篇文章的基础之后,下面的内容理解起来也会相对容易,所以不会做过多说明,代码中注释也比较详细。所以直接贴代码例子鸟~大家可以下载源代码然后运行查看输出的信息,就可以更清楚地深入了解它们了~

线程组(Group)

-(void)testGroup
{
    //将任务添加到线程组后,当组中所有任务都执行完毕后
    //线程组会向我们发出通知,可以在该队列的notify方法中执行特定任务。
    //特别需要注意的一点就是,是在该线程组中所有的队列的所有的任务都执行完才会调用特定队列的notify方法的
    //如果该组有多个队列,则所有队列的notify将要在所有队列的任务都执行完时才会被调用

    //创建一个队列组
    dispatch_group_t group = dispatch_group_create();

    //自定义一个串行队列
    dispatch_queue_t myQueue = dispatch_queue_create("com.lysongzi.myqueue", DISPATCH_QUEUE_PRIORITY_DEFAULT);

    //获取全局队列
    dispatch_queue_t gloabalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    //添加异步执行的任务,组里的任务都是异步执行的
    dispatch_group_async(group, myQueue, ^{
        for (int i = 0; i < 3; i++) {
            NSLog(@"group-queue01 ==> %d ==> %@", i, [NSThread currentThread]);
        }
    });

    dispatch_group_async(group, gloabalQueue, ^{
        for (int i = 0; i < 10; i++) {
            NSLog(@"group-queue02-thread01 ==> %d ==> %@", i, [NSThread currentThread]);
        }
    });

    dispatch_group_async(group, gloabalQueue, ^{
        for (int i = 0; i < 6; i++) {
            NSLog(@"group-queue02-thread02 ==> %d ==> %@", i, [NSThread currentThread]);
        }
    });

    //设置任务执行完后通知执行的内容
    //测试结果可知,会在该组中的相应队列的最后一个执行完的任务所在线程执行这个通知的方法。
    dispatch_group_notify(group, myQueue, ^{
        NSLog(@"Group in mainQueue finish. %@", [NSThread currentThread]);
    });

    dispatch_group_notify(group, gloabalQueue, ^{
        NSLog(@"Group in gloabalQueue finish. %@", [NSThread currentThread]);
    });
}

栅栏(Barrier)

- (void)testBarrier
{
    dispatch_queue_t queue = dispatch_queue_create("com.lysongzi.barrier.concurrent", DISPATCH_QUEUE_CONCURRENT);

    dispatch_async(queue, ^{
        for (int i = 0; i < 15; i++) {
            NSLog(@"before barrier01 ==> %d ==> %@", i, [NSThread currentThread]);
        }
    });

    dispatch_async(queue, ^{
        for (int i = 0; i < 15; i++) {
            NSLog(@"before barrier02 ==> %d ==> %@", i, [NSThread currentThread]);
        }
    });

    //创建一个barrier任务,此后添加的任务需要在该任务执行完之后才会开始执行
    dispatch_barrier_async(queue, ^{
        NSLog(@"This is barrier task");
    });

    dispatch_async(queue, ^{
        for (int i = 0; i < 15; i++) {
            NSLog(@"after barrier01 ==> %d ==> %@", i, [NSThread currentThread]);
        }
    });

    dispatch_async(queue, ^{
        for (int i = 0; i < 15; i++) {
            NSLog(@"after barrier02 ==> %d ==> %@", i, [NSThread currentThread]);
        }
    });
}

单例(Once)

额,这里的单例主要是该方法常见用于单例实现中,其主要的含义是确保某个任务只被执行一次。

+(instancetype)sharedInstance
{
    static dispatch_once_t once;
    static id _instance;

    if (!_instance) {
        dispatch_once(&once, ^{
            _instance = [[self alloc] init];;
        });
    }

    return _instance;
}

延时处理

这里是一个延时2秒执行特定任务的方法。更多延时处理方法可以参考iOS-延迟操作方法总结

-(void)testAfter
{
    NSLog(@"%@", [NSDate new]);
    dispatch_time_t start = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC));
    dispatch_after(start, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"延迟执行的任务.");
        NSLog(@"%@", [NSDate new]);
    });
}

迭代

-(void)testApply
{
    //参数一:迭代次数
    //参数二:任务队列
    //参数三:迭代执行的代码块
    //迭代是异步的
    dispatch_apply(10, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t index) {
        NSLog(@"apply %zu.", index);
    });
}

计时器

-(void)testGCDTime
{
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    //创建一个定时起源
    dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);

    //设置回调时间间隔
    int64_t interval = (int64_t)(1 * NSEC_PER_SEC);
    //设置定时器开始时间
    dispatch_time_t start = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC));

    //启动计时器
    //参数1:timer
    //参数2:开始时间
    //参数3:时间间隔
    //参数4:0
    dispatch_source_set_timer(source, start, interval, 0);

    //设置回调事件,即每次定时器触发的处理时间
    dispatch_source_set_event_handler(source, ^{
        static int number = 0;
        NSLog(@"%d", number);

        number++;
        //运行到第6秒则取消计时器
        if (number == 6) {
            dispatch_source_cancel(source);
            NSLog(@"Cancle timer.");
        }
    });

    //启动定时器
    dispatch_resume(source);
}

源代码

Github-GCDDemon

参考资料

  1. 苹果官方文档-Grand Central Dispatch (GCD) Reference
  2. iOS开发–四种多线程技术方案
  3. GCD实践——GCD线程组
  4. GCD实践——GCD延时执行
  5. GCD实践——GCD定时器