美文网首页
GCD 相关函数

GCD 相关函数

作者: xiaofu666 | 来源:发表于2021-09-03 20:07 被阅读0次
  1. 串行同步
    // 串行队列
    dispatch_queue_t queue = dispatch_queue_create("com.sf.test", DISPATCH_QUEUE_SERIAL);
    // 同步执行
    dispatch_sync(queue, ^{
        for (int i = 0; i < 3; i++) {
            NSLog(@"串行同步1 %@",[NSThread currentThread]);
        }
    });
    dispatch_sync(queue, ^{
        for (int i = 0; i < 3; i++) {
            NSLog(@"串行同步2 %@",[NSThread currentThread]);
        }
    });
    dispatch_sync(queue, ^{
        for (int i = 0; i < 3; i++) {
            NSLog(@"串行同步3 %@",[NSThread currentThread]);
        }
    });
  1. 串行异步
    // 串行队列
    dispatch_queue_t queue = dispatch_queue_create("com.sf.test", DISPATCH_QUEUE_SERIAL);
    // 异步执行
    dispatch_async(queue, ^{
        for (int i = 0; i < 3; i++) {
            NSLog(@"串行异步1 %@",[NSThread currentThread]);
        }
    });
    dispatch_async(queue, ^{
        for (int i = 0; i < 3; i++) {
            NSLog(@"串行异步2 %@",[NSThread currentThread]);
        }
    });
    dispatch_async(queue, ^{
        for (int i = 0; i < 3; i++) {
            NSLog(@"串行异步3 %@",[NSThread currentThread]);
        }
    });
  1. 并行同步
    // 并行队列
    dispatch_queue_t queue = dispatch_queue_create("com.sf.test", DISPATCH_QUEUE_CONCURRENT);
    // 同步执行
    dispatch_sync(queue, ^{
        for (int i = 0; i < 3; i++) {
            NSLog(@"并行同步1 %@",[NSThread currentThread]);
        }
    });
    dispatch_sync(queue, ^{
        for (int i = 0; i < 3; i++) {
            NSLog(@"并行同步2 %@",[NSThread currentThread]);
        }
    });
    dispatch_sync(queue, ^{
        for (int i = 0; i < 3; i++) {
            NSLog(@"并行同步3 %@",[NSThread currentThread]);
        }
    });
  1. 并行异步
    // 并行队列
    dispatch_queue_t queue = dispatch_queue_create("com.sf.test", DISPATCH_QUEUE_CONCURRENT);
    // 异步执行
    dispatch_sync(queue, ^{
        for (int i = 0; i < 3; i++) {
            NSLog(@"并行异步1 %@",[NSThread currentThread]);
        }
    });
    dispatch_sync(queue, ^{
        for (int i = 0; i < 3; i++) {
            NSLog(@"并行异步2 %@",[NSThread currentThread]);
        }
    });
    dispatch_sync(queue, ^{
        for (int i = 0; i < 3; i++) {
            NSLog(@"并行异步3 %@",[NSThread currentThread]);
        }
    });
  1. 主队列同步 会死锁
    NSLog(@"\n\n**************主队列同步,放到主线程会死锁***************\n\n");
    // 主队列
    dispatch_queue_t queue = dispatch_get_main_queue();
    // 同步执行
    dispatch_sync(queue, ^{
        for (int i = 0; i < 3; i++) {
            NSLog(@"主队列同步1 %@",[NSThread currentThread]);
        }
    });
    dispatch_sync(queue, ^{
        for (int i = 0; i < 3; i++) {
            NSLog(@"主队列同步2 %@",[NSThread currentThread]);
        }
    });
  1. 主队列异步
    NSLog(@"\n\n**************主队列异步,串行执行***************\n\n");
    // 主队列
    dispatch_queue_t queue = dispatch_get_main_queue();
    // 同步执行
    dispatch_async(queue, ^{
        for (int i = 0; i < 3; i++) {
            NSLog(@"主队列异步1 %@",[NSThread currentThread]);
        }
    });
    dispatch_async(queue, ^{
        for (int i = 0; i < 3; i++) {
            NSLog(@"主队列异步2 %@",[NSThread currentThread]);
        }
    });
  1. 异步处理耗时,回主线程刷新UI
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"异步处理耗时数据 %@",[NSThread currentThread]);
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"主线程刷新UI %@",[NSThread currentThread]);
        });
    });
  1. 栅栏函数
    dispatch_queue_t queue = dispatch_queue_create("com.sf.test", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
        for (int i = 0; i < 3; i++) {
            NSLog(@"并发异步执行1 %@",[NSThread currentThread]);
        }
    });
    dispatch_async(queue, ^{
        for (int i = 0; i < 3; i++) {
            NSLog(@"并发异步执行2 %@",[NSThread currentThread]);
        }
    });
    dispatch_barrier_async(queue, ^{
        NSLog(@"\n\n**************barrier**************\n\n");
    });
    dispatch_async(queue, ^{
        for (int i = 0; i < 3; i++) {
            NSLog(@"并发异步执行3 %@",[NSThread currentThread]);
        }
    });
    dispatch_async(queue, ^{
        for (int i = 0; i < 3; i++) {
            NSLog(@"并发异步执行4 %@",[NSThread currentThread]);
        }
    });
  1. 延时执行
    //相对时间
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5.0 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
        NSLog(@"延迟5秒执行");
    });
    //绝对时间 (NUll表示自动获取当前时区的当前时间作为开始时刻)
    dispatch_after(dispatch_walltime(NULL, 5.0 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
        NSLog(@"延迟5秒执行");
    });

    //设置固定时间,可做定时任务
    NSDateFormatter *formatter = [NSDateFormatter new];
    formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss";
    struct timespec time;
    time.tv_sec = (NSInteger)[[formatter dateFromString:@"2020-02-02 11:11:11"] timeIntervalSince1970];
    //比固定的时间点再晚10秒
    dispatch_time_t timer = dispatch_walltime(&time, 10*NSEC_PER_SEC);
    dispatch_after(timer, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        NSLog(@"2020-02-02 11:11:11 时间延迟10秒后执行");
    });

时间单位

#define NSEC_PER_SEC    1000000000ull     //每秒有1000000000纳秒
#define NSEC_PER_MSEC   1000000ull        //每毫秒有1000000纳秒
#define USEC_PER_SEC    1000000ull        //每秒有1000000微秒
#define NSEC_PER_USEC   1000ull           //每微秒有1000纳秒

1秒的写作方式可以是
1 * NSEC_PER_SEC;
1000 * NSEC_PER_MSEC;
USEC_PER_SEC * NSEC_PER_USEC

  1. 单例函数
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSLog(@"程序只执行了一次");
    });
  1. 快速遍历
    //这个顺序是随机的,并发的
    dispatch_queue_t queue = dispatch_queue_create("com.sf.test", DISPATCH_QUEUE_CONCURRENT);
    dispatch_apply(10, queue, ^(size_t index) {
        NSLog(@"dispatch_apply : %zd---%@",index,[NSThread currentThread]);
    });
  1. 队列函数
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_async(group, dispatch_queue_create(0, 0), ^{
        NSLog(@"队列组1:一个耗时操作已完成!");
    });
    dispatch_group_async(group, dispatch_queue_create(0, 0), ^{
        NSLog(@"队列组2:一个耗时操作已完成!");
    });
    dispatch_group_async(group, dispatch_queue_create(0, 0), ^{
        NSLog(@"队列组3:一个耗时操作已完成!");
    });
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"队列组:前面的耗时操作都完成了,回到主线程");
    });

多网络请求完成模拟

    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
    [request setURL:[NSURL URLWithString:@"https://baidu.com"]];
    [request setTimeoutInterval:3];//超时时间
    [request setHTTPMethod:@"GET"];
    
    dispatch_group_t group = dispatch_group_create();
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    dispatch_group_async(group, queue, ^{
        dispatch_group_enter(group);
        NSURLSessionDataTask *task=[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            NSLog(@"队列组网络请求1:一个耗时操作已完成!");
            dispatch_group_leave(group);
        }];
        [task resume];
    });
    dispatch_group_async(group, queue, ^{
        dispatch_group_enter(group);
        NSURLSessionDataTask *task=[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            NSLog(@"队列组网络请求2:一个耗时操作已完成!");
            dispatch_group_leave(group);
        }];
        [task resume];
    });
    dispatch_group_async(group, queue, ^{
        dispatch_group_enter(group);
        NSURLSessionDataTask *task=[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            NSLog(@"队列组网络请求3:一个耗时操作已完成!");
            dispatch_group_leave(group);
        }];
        [task resume];
    });
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"队列组:前面的耗时操作都完成了,回到主线程");
    });
  1. 定时器
    __block NSInteger timeOut = 10;
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    dispatch_source_set_timer(timer,
                              dispatch_time(DISPATCH_TIME_NOW, 0 * NSEC_PER_SEC),
                              1 * NSEC_PER_SEC, 0);
    dispatch_source_set_event_handler(timer, ^{
        
        if (timeOut <= 0) {
            dispatch_source_cancel(timer);
            NSLog(@"定时器停止");
        } else {
            NSLog(@"执行任务");
            timeOut--;
        }
    });
    dispatch_resume(timer);
  1. 信号量
- (void)main{
    self.semaphore = dispatch_semaphore_create(0);
    [self semaphorePlus];
    [self semaphoreWait];
}
- (void)semaphoreWait{
    // 如果信号量的值 > 0,就让信号量的值减1,然后继续往下执行代码
    // 如果信号量的值 <= 0,就会休眠等待,直到信号量的值变成>0,就让信号量的值减1,然后继续往下执行代码
    NSLog(@"开始等待");
    dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
    NSLog(@"等待结束");
    
}
- (void)semaphorePlus{
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5.0 * NSEC_PER_SEC), dispatch_get_global_queue(0, 0), ^{
        NSLog(@"延迟5秒执行");
        NSLog(@"信号量加1");
        dispatch_semaphore_signal(self.semaphore);
    });
}
  1. 设置优先级
dispatch_queue_t myQueue = dispatch_queue_create("com.sf.test", NULL); 
dispatch_queue_t globalHightQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
//第一个参数为要设置优先级的queue,第二个参数是参照物,既将第一个queue的优先级和第二个queue的优先级设置一样。
dispatch_set_target_queue(myQueue, globalHighQueue);

GCD相关函数说明

1. Dispatch Queue

//各种队列的获取方法
-(void)getQueue{

    //主队列的获取方法:主队列是串行队列,主队列中的任务都将在主线程中执行
    dispatch_queue_t mainqueue = dispatch_get_main_queue();

    //串行队列的创建方法:第一个参数表示队列的唯一标识,第二个参数用来识别是串行队列还是并发队列(若为NULL时,默认是DISPATCH_QUEUE_SERIAL)
    dispatch_queue_t seriaQueue = dispatch_queue_create("com.test.testQueue", DISPATCH_QUEUE_SERIAL);

    //并发队列的创建方法:第一个参数表示队列的唯一标识,第二个参数用来识别是串行队列还是并发队列(若为NULL时,默认是DISPATCH_QUEUE_SERIAL)
    dispatch_queue_t concurrentQueue = dispatch_queue_create("com.test.testQueue", DISPATCH_QUEUE_CONCURRENT);

    //全局并发队列的获取方法:第一个参数表示队列优先级,我们选择默认的好了,第二个参数flags作为保留字段备用,一般都直接填0
    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
}

2. dispatch_queue_creat

//自定义队列的创建方法
-(void)queue_create{
    //串行队列的创建方法:第一个参数表示队列的唯一标识,第二个参数用来识别是串行队列还是并发队列(若为NULL时,默认是DISPATCH_QUEUE_SERIAL)
    dispatch_queue_t seriaQueue = dispatch_queue_create("com.test.testQueue", DISPATCH_QUEUE_SERIAL);

    //并发队列的创建方法:第一个参数表示队列的唯一标识,第二个参数用来识别是串行队列还是并发队列(若为NULL时,默认是DISPATCH_QUEUE_SERIAL)
    dispatch_queue_t concurrentQueue = dispatch_queue_create("com.test.testQueue", DISPATCH_QUEUE_CONCURRENT);
}

3. dispatch_set_target_queue

  • dispatch_set_target_queue可以更改Dispatch Queue的执行优先级 dispatch_queue_create函数生成的DisPatch Queue不管是Serial DisPatch Queue还是Concurrent Dispatch Queue,执行的优先级都与默认优先级的Global Dispatch queue相同,如果需要变更生成的Dispatch Queue的执行优先级则需要使用dispatch_set_target_queue函数。
//使用dispatch_set_target_queue更改Dispatch Queue的执行优先级
-(void)testTargetQueue1{

    NSLog(@"----start-----当前线程---%@",[NSThread currentThread]);

    //串行队列的创建方法:第一个参数表示队列的唯一标识,第二个参数用来识别是串行队列还是并发队列(若为NULL时,默认是DISPATCH_QUEUE_SERIAL)
    dispatch_queue_t seriaQueue = dispatch_queue_create("com.test.testQueue", NULL);

    //指定一个任务
    dispatch_async(seriaQueue, ^{

        //这里线程暂停2秒,模拟一般的任务的耗时操作
        [NSThread sleepForTimeInterval:2];

        NSLog(@"----执行第一个任务---当前线程%@",[NSThread currentThread]);
    });

    //全局并发队列的获取方法:第一个参数表示队列优先级,我们选择默认的好了,第二个参数flags作为保留字段备用,一般都直接填0
    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    //指定一个任务
    dispatch_async(globalQueue, ^{

        //这里线程暂停2秒,模拟一般的任务的耗时操作
        [NSThread sleepForTimeInterval:2];

        NSLog(@"----执行第二个任务---当前线程%@",[NSThread currentThread]);
    });

    //第一个参数为要设置优先级的queue,第二个参数是参照物,即将第一个queue的优先级和第二个queue的优先级设置一样。
    //第一个参数如果是系统提供的【主队列】或【全局队列】,则不知道会出现什么情况,因此最好不要设置第一参数为系统提供的队列
    dispatch_set_target_queue(seriaQueue,globalQueue);

    NSLog(@"----end-----当前线程---%@",[NSThread currentThread]);

}
  • dispatch_set_target_queue除了能用来设置队列的优先级之外,还能够创建队列的层次体系,当我们想让不同队列中的任务同步的执行时,我们可以创建一个串行队列,然后将这些队列的target指向新创建的队列即可。
- (void)testTargetQueue2 {

    NSLog(@"----start-----当前线程---%@",[NSThread currentThread]);

    dispatch_queue_t targetQueue = dispatch_queue_create("com.test.target_queue", DISPATCH_QUEUE_SERIAL);

    dispatch_queue_t queue1 = dispatch_queue_create("com.test.queue1", DISPATCH_QUEUE_SERIAL);

    dispatch_queue_t queue2 = dispatch_queue_create("com.test.queue2", DISPATCH_QUEUE_CONCURRENT);

    dispatch_set_target_queue(queue1, targetQueue);

    dispatch_set_target_queue(queue2, targetQueue);

    //指定一个异步任务
    dispatch_async(queue1, ^{
        NSLog(@"----执行第一个任务---当前线程%@",[NSThread currentThread]);
        [NSThread sleepForTimeInterval:2];
    });

    //指定一个异步任务
    dispatch_async(queue2, ^{
        NSLog(@"----执行第二个任务---当前线程%@",[NSThread currentThread]);
        [NSThread sleepForTimeInterval:2];
    });

    //指定一个异步任务
    dispatch_async(queue2, ^{
        NSLog(@"----执行第三个任务---当前线程%@",[NSThread currentThread]);
        [NSThread sleepForTimeInterval:2];
    });

    NSLog(@"----end-----当前线程---%@",[NSThread currentThread]);

}

4. dispatch_after

//延时执行,需要注意的是:dispatch_after函数并不是在指定时间之后才开始执行处理,而是在指定时间之后将任务追加到主队列中。严格来说,这个时间并不是绝对准确的,但想要大致延迟执行任务,dispatch_after函数是很有效的。
-(void)dispatch_after{
    NSLog(@"----start-----当前线程---%@",[NSThread currentThread]);

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        // 2秒后异步追加任务代码到主队列等待执行
        NSLog(@"----执行第一个任务---当前线程%@",[NSThread currentThread]);
    });

    NSLog(@"----end-----当前线程---%@",[NSThread currentThread]);

}

5. dispatch_once

//只执行一次,通常在创建单例时使用,多线程环境下也能保证线程安全
-(void)dispatch_once_1{

    NSLog(@"----start-----当前线程---%@",[NSThread currentThread]);

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSLog(@"----只执行一次的任务---当前线程%@",[NSThread currentThread]);
    });

    NSLog(@"----end-----当前线程---%@",[NSThread currentThread]);

}

6. dispatch_apply

//快速遍历方法,可以替代for循环的函数。dispatch_apply按照指定的次数将指定的任务追加到指定的队列中,并等待全部队列执行结束。
//会创建新的线程,并发执行
-(void)dispatch_apply{

    NSLog(@"----start-----当前线程---%@",[NSThread currentThread]);

    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    dispatch_apply(100, globalQueue, ^(size_t index) {
        NSLog(@"执行第%zd次的任务---%@",index, [NSThread currentThread]);
    });

    NSLog(@"----end-----当前线程---%@",[NSThread currentThread]);

}

7. dispatch_group

//队列组:当我们遇到需要异步下载3张图片,都下载完之后再拼接成一个整图的时候,就需要用到gcd队列组。
-(void)dispatch_group{

    NSLog(@"----start-----当前线程---%@",[NSThread currentThread]);

    dispatch_group_t group =  dispatch_group_create();

    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // 第一个任务
        [NSThread sleepForTimeInterval:2];

        NSLog(@"----执行第一个任务---当前线程%@",[NSThread currentThread]);

    });

    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // 第二个任务
        [NSThread sleepForTimeInterval:2];

        NSLog(@"----执行第二个任务---当前线程%@",[NSThread currentThread]);
    });

    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        // 第三个任务
        [NSThread sleepForTimeInterval:2];

        NSLog(@"----执行第三个任务---当前线程%@",[NSThread currentThread]);
    });

    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        [NSThread sleepForTimeInterval:2];

        NSLog(@"----执行最后的汇总任务---当前线程%@",[NSThread currentThread]);
    });

    //若想执行完上面的任务再走下面这行代码可以加上下面这句代码

    // 等待上面的任务全部完成后,往下继续执行(会阻塞当前线程)
    //    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

    NSLog(@"----end-----当前线程---%@",[NSThread currentThread]);
}
  • dispatch_group_enter 标志着一个任务追加到 group,执行一次,相当于 group 中未执行完毕任务数+1
  • dispatch_group_leave 标志着一个任务离开了 group,执行一次,相当于 group 中未执行完毕任务数-1。
  • 当 group 中未执行完毕任务数为0的时候,才会使dispatch_group_wait解除阻塞,以及执行追加到dispatch_group_notify中的任务。
-(void)dispatch_group_1{

    NSLog(@"----start-----当前线程---%@",[NSThread currentThread]);

    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, ^{
        // 第一个任务
        [NSThread sleepForTimeInterval:2];

        NSLog(@"----执行第一个任务---当前线程%@",[NSThread currentThread]);

        dispatch_group_leave(group);
    });

    dispatch_group_enter(group);
    dispatch_async(queue, ^{
        // 第二个任务
        [NSThread sleepForTimeInterval:2];

        NSLog(@"----执行第二个任务---当前线程%@",[NSThread currentThread]);

        dispatch_group_leave(group);
    });

    dispatch_group_enter(group);
    dispatch_async(queue, ^{
        // 第三个任务
        [NSThread sleepForTimeInterval:2];

        NSLog(@"----执行第三个任务---当前线程%@",[NSThread currentThread]);

        dispatch_group_leave(group);
    });

    dispatch_group_notify(group, dispatch_get_main_queue(), ^{

        [NSThread sleepForTimeInterval:2];
        NSLog(@"----执行最后的汇总任务---当前线程%@",[NSThread currentThread]);
    });

    NSLog(@"----end-----当前线程---%@",[NSThread currentThread]);

}

8. dispatch_semaphore

//信号量
//总结:信号量设置的是2,在当前场景下,同一时间内执行的线程就不会超过2,先执行2个线程,等执行完一个,下一个会开始执行。
-(void)dispatch_semaphore{

    NSLog(@"----start-----当前线程---%@",[NSThread currentThread]);

    dispatch_semaphore_t semaphore = dispatch_semaphore_create(2);

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    //任务1
    dispatch_async(queue, ^{

        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

        NSLog(@"----开始执行第一个任务---当前线程%@",[NSThread currentThread]);

        [NSThread sleepForTimeInterval:2];

        NSLog(@"----结束执行第一个任务---当前线程%@",[NSThread currentThread]);

        dispatch_semaphore_signal(semaphore);
    });

    //任务2
    dispatch_async(queue, ^{

        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

        NSLog(@"----开始执行第二个任务---当前线程%@",[NSThread currentThread]);

        [NSThread sleepForTimeInterval:1];

        NSLog(@"----结束执行第二个任务---当前线程%@",[NSThread currentThread]);

        dispatch_semaphore_signal(semaphore);
    });

    //任务3
    dispatch_async(queue, ^{

        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

        NSLog(@"----开始执行第三个任务---当前线程%@",[NSThread currentThread]);

        [NSThread sleepForTimeInterval:2];

        NSLog(@"----结束执行第三个任务---当前线程%@",[NSThread currentThread]);

        dispatch_semaphore_signal(semaphore);
    });

    NSLog(@"----end-----当前线程---%@",[NSThread currentThread]);

}

9. Dispatch I/O

//以下为苹果中使用Dispatch I/O和Dispatch Data的例子
pipe_q = dispatch_queue_create("PipeQ",NULL);
pipe_channel = dispatch_io_create(DISPATCH_IO_STREAM,fd,pipe_q,^(int err){
   close(fd);
});

*out_fd = fdpair[I];

dispatch_io_set_low_water(pipe_channel,SIZE_MAX);

dispatch_io_read(pipe_channel,0,SIZE_MAX,pipe_q, ^(bool done,dispatch_data_t pipe data,int err){
   if(err == 0)
     {
       size_t len = dispatch_data_get_size(pipe data);
       if(len > 0)
       {
          const char *bytes = NULL;
          char *encoded;

          dispatch_data_t md = dispatch_data_create_map(pipe data,(const void **)&bytes,&len);
          asl_set((aslmsg)merged_msg,ASL_KEY_AUX_DATA,encoded);
          free(encoded);
          _asl_send_message(NULL,merged_msg,-1,NULL);
          asl_msg_release(merged_msg);
          dispatch_release(md);
       }
      }

      if(done)
      {
         dispatch_semaphore_signal(sem);
         dispatch_release(pipe_channel);
         dispatch_release(pipe_q);
      }
});

10. dispatch_barrier_async

//隔断方法:当前面的写入操作全部完成之后,再执行后面的读取任务。当然也可以用Dispatch Group和dispatch_set_target_queue,只是比较而言,dispatch_barrier_async会更加顺滑
-(void)dispatch_barrier_async{

    NSLog(@"----start-----当前线程---%@",[NSThread currentThread]);

    dispatch_queue_t queue = dispatch_queue_create("com.test.testQueue", DISPATCH_QUEUE_CONCURRENT);

    dispatch_async(queue, ^{
        // 第一个写入任务
        [NSThread sleepForTimeInterval:3];

        NSLog(@"----执行第一个写入任务---当前线程%@",[NSThread currentThread]);

    });
    dispatch_async(queue, ^{
        // 第二个写入任务
        [NSThread sleepForTimeInterval:1];

        NSLog(@"----执行第二个任务---当前线程%@",[NSThread currentThread]);

    });

    dispatch_barrier_async(queue, ^{
        // 等待处理
        [NSThread sleepForTimeInterval:2];

        NSLog(@"----等待前面的任务完成---当前线程%@",[NSThread currentThread]);

    });

    dispatch_async(queue, ^{
        // 第一个读取任务
        [NSThread sleepForTimeInterval:2];

        NSLog(@"----执行第一个读取任务---当前线程%@",[NSThread currentThread]);

    });
    dispatch_async(queue, ^{
        // 第二个读取任务
        [NSThread sleepForTimeInterval:2];

        NSLog(@"----执行第二个读取任务---当前线程%@",[NSThread currentThread]);

    });

    NSLog(@"----end-----当前线程---%@",[NSThread currentThread]);

}

11. dispatch_suspend & dispatchp_resume

//场景:当追加大量处理到Dispatch Queue时,在追加处理的过程中,有时希望不执行已追加的处理。例如演算结果被Block截获时,一些处理会对这个演算结果造成影响。在这种情况下,只要挂起Dispatch Queue即可。当可以执行时再恢复。
//总结:dispatch_suspend,dispatch_resume提供了“挂起、恢复”队列的功能,简单来说,就是可以暂停、恢复队列上的任务。但是这里的“挂起”,并不能保证可以立即停止队列上正在运行的任务,也就是如果挂起之前已经有队列中的任务在进行中,那么该任务依然会被执行完毕
-(void)dispatch_suspend{

    NSLog(@"----start-----当前线程---%@",[NSThread currentThread]);

    dispatch_queue_t queue = dispatch_queue_create("com.test.testQueue", DISPATCH_QUEUE_SERIAL);

    dispatch_async(queue, ^{
        // 执行第一个任务
        [NSThread sleepForTimeInterval:5];

        NSLog(@"----执行第一个任务---当前线程%@",[NSThread currentThread]);

    });

    dispatch_async(queue, ^{
        // 执行第二个任务
        [NSThread sleepForTimeInterval:5];

        NSLog(@"----执行第二个任务---当前线程%@",[NSThread currentThread]);

    });

    dispatch_async(queue, ^{
        // 执行第三个任务
        [NSThread sleepForTimeInterval:5];

        NSLog(@"----执行第三个任务---当前线程%@",[NSThread currentThread]);
    });

    //此时发现意外情况,挂起队列
    NSLog(@"suspend");
    dispatch_suspend(queue);

    //挂起10秒之后,恢复正常
    [NSThread sleepForTimeInterval:10];

    //恢复队列
    NSLog(@"resume");
    dispatch_resume(queue);

    NSLog(@"----end-----当前线程---%@",[NSThread currentThread]);

}

相关文章

网友评论

      本文标题:GCD 相关函数

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