美文网首页
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