多线程之GCD队列组

GCD 队列组:dispatch_group

有时候我们会有这样的需求:分别异步执行2个耗时任务,然后当2个耗时任务都执行完毕后再回到主线程执行任务。这时候我们可以用到 GCD的队列组。

  • 调用队列组的 dispatch_group_async 先把任务放到队列中,然后将队列放入队列组中。或者使用队列组的 dispatch_group_enterdispatch_group_leave 组合 来实现dispatch_group_async
  • 调用队列组的 dispatch_group_notify 回到指定线程执行任务。或者使用 dispatch_group_wait回到当前线程继续向下执行(会阻塞当前线程)。

dispatch_group_notify

监听 group中任务的完成状态,当所有的任务都执行完成后,追加任务到 group中,并执行任务。

/**
 * 队列组 dispatch_group_notify
 */
- (void)groupNotify {
    
    // 打印当前线程
    NSLog(@"currentThread-->%@",[NSThread currentThread]);
    NSLog(@"group-->begin");
    dispatch_group_t group =  dispatch_group_create();
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    dispatch_group_async(group, queue, ^{
        // 追加任务1
        for (int i = 0; i < 2; ++i) {
            // 模拟耗时操作
            [NSThread sleepForTimeInterval:2];
            // 打印当前线程
            NSLog(@"1-->%@",[NSThread currentThread]);
        }
    });
    dispatch_group_async(group, queue, ^{
        // 追加任务2
        for (int i = 0; i < 2; ++i) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"2-->%@",[NSThread currentThread]);
        }
    });
    
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        // 等前面的异步任务1、任务2都执行完毕后,回到主线程执行下边任务
        for (int i = 0; i < 2; ++i) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"3-->%@",[NSThread currentThread]);
        }
        NSLog(@"group-->end");
    });
}

输出结果

currentThread-->{number = 1, name = main}
group-->begin
1-->{number = 5, name = (null)}
2-->{number = 6, name = (null)}
2-->{number = 6, name = (null)}
1-->{number = 5, name = (null)}
3-->{number = 1, name = main}
3-->{number = 1, name = main}
group-->end

dispatch_group_notify相关代码运行输出结果可以看出:当所有任务都执行完成之后,才执行dispatch_group_notify block中的任务。

dispatch_group_wait

暂停当前线程(阻塞当前线程),等待指定的 group中的任务执行完成后,才会往下继续执行。

/**
 * 队列组 dispatch_group_wait
 */
- (void)groupWait {
    
    NSLog(@"currentThread-->%@",[NSThread currentThread]);
    NSLog(@"group-->begin");
    dispatch_group_t group =  dispatch_group_create();
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    dispatch_group_async(group, queue, ^{
        // 追加任务1
        for (int i = 0; i < 2; ++i) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"1-->%@",[NSThread currentThread]);
        }
    });
    dispatch_group_async(group, queue, ^{
        // 追加任务2
        for (int i = 0; i < 2; ++i) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"2-->%@",[NSThread currentThread]);
        }
    });
    // 等待上面的任务全部完成后,会往下继续执行(会阻塞当前线程)
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    NSLog(@"group-->end");
}

输出结果

currentThread-->{number = 1, name = main}
group-->begin
2-->{number = 5, name = (null)}
1-->{number = 4, name = (null)}
2-->{number = 5, name = (null)}
1-->{number = 4, name = (null)}
group-->end

dispatch_group_wait相关代码运行输出结果可以看出:当所有任务执行完成之后,才执行 dispatch_group_wait之后的操作。但是,使用dispatch_group_wait 会阻塞当前线程。

dispatch_group_enterdispatch_group_leave

  • dispatch_group_enter标志着一个任务追加到 group,执行一次,相当于group 中未执行完毕任务数+1
  • dispatch_group_leave标志着一个任务离开了 group,执行一次,相当于group 中未执行完毕任务数-1。
  • group中未执行完毕任务数为0的时候,才会使dispatch_group_wait解除阻塞,以及执行追加到dispatch_group_notify中的任务。
/**
 * 队列组 dispatch_group_enter、dispatch_group_leave
 */
- (void)groupEnterAndLeave {
    
    NSLog(@"currentThread-->%@",[NSThread currentThread]);
    NSLog(@"group-->begin");
    dispatch_group_t group = dispatch_group_create();
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_enter(group);
    
    dispatch_async(queue, ^{
        // 追加任务1
        for (int i = 0; i < 2; ++i) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"1-->%@",[NSThread currentThread]);
        }
        dispatch_group_leave(group);
    });
    
    dispatch_group_enter(group);
    dispatch_async(queue, ^{
        // 追加任务2
        for (int i = 0; i < 2; ++i) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"2-->%@",[NSThread currentThread]);
        }
        dispatch_group_leave(group);
    });
    
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        // 等前面的异步操作都执行完毕后,回到主线程.
        for (int i = 0; i < 2; ++i) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"3-->%@",[NSThread currentThread]);
        }
        NSLog(@"group_notify-->end");
    });
    // 等待上面的任务全部完成后,会往下继续执行(会阻塞当前线程)
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    NSLog(@"group---end");
}

输出

currentThread-->{number = 1, name = main}
group-->begin
1-->{number = 4, name = (null)}
2-->{number = 3, name = (null)}
2-->{number = 3, name = (null)}
1-->{number = 4, name = (null)}
group---end
3-->{number = 1, name = main}
3-->{number = 1, name = main}
group_notify-->end

dispatch_group_enterdispatch_group_leave相关代码运行结果中可以看出:当所有任务执行完成之后,才执行dispatch_group_notify 中的任务。这里的dispatch_group_enterdispatch_group_leave组合,其实等同于dispatch_group_async

你可能感兴趣的:(多线程之GCD队列组)