zoukankan      html  css  js  c++  java
  • GCD 信号量使用记录

    需求:

    现在有一个页面,有A, B, C 3个网络请求。A, B是非必须,C是必须,所有请求完毕之后要刷新tableView。

    这里当然可以使用异步并发,每个请求的成功或者失败中刷新tableView。

    如果要用信号量来控制呢?顺便复习一遍吧。

    信号量(Semaphore)是多线程环境下的一种保护设施,可以用来保证两个或多个关键代码不被并发调用。
    
    在进入一个关键代码段之前,线程必须获取一个信号量。一旦执行完毕,该线程就会释放信号量。等待下一个信号量被发送,线程才能继续获取到新信号量并再次执行关键代码段。

    举个例子:
    一个停车场,只能容下5辆车。这时候,来了6辆车。只有前5辆能进去。第6辆车等待,当有一辆车离开停车场时,才能进入。
    这里,
    想进停车场 —— 创建信号,
    当前有车位 ,领卡进场 —— 发信号,
    当前无车位,排队等卡 —— 等信号,
    离开停车场 —— 销毁信号。
     
    dispatch_semaphore_create(long value); //!< 创建信号量
    dispatch_semaphore_signal(dispatch_semaphore_t dsema); //!< 发送信号量 +1

    dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout); //!< 等待信号量 -1


    作者:QiShare
    链接:https://www.jianshu.com/p/0ae764495c9b
    来源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
     

    当信号量为<0时就会阻塞线程,>=0时就继续走。发送信号量 +1 & 等待信号量 -1 是成对出现的

    所以 dispatch_semaphore_create(?)函数指定信号量,看情况,一般是指定0

    测试代码:

    -(void)dispatch_group_function1

    {

        dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

        

        dispatch_group_t group = dispatch_group_create();

        

        dispatch_group_async(group, dispatch_queue_create("com.dispatch.test", DISPATCH_QUEUE_CONCURRENT), ^{

            

            NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:@"https://www.baidu.com"]];

            

            NSURLSessionDownloadTask *task = [[NSURLSession sharedSession] downloadTaskWithRequest:request completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {

                // 请求完成,可以通知界面刷新界面等操作

                NSLog(@"第一步网络请求完成");

                

                // 使信号的信号量+1,这里的信号量本来为0,+1信号量为1(绿灯)

                dispatch_semaphore_signal(semaphore);

            }];

            

            [task resume];

            

            // 以下还要进行一些其他的耗时操作

            NSLog(@"耗时操作继续进行%@",[NSThread currentThread]);

            

            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

        });

        

        dispatch_group_async(group, dispatch_queue_create("com.dispatch.test", DISPATCH_QUEUE_CONCURRENT), ^{

            

            NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:@"https://www.github.com"]];

            

            NSURLSessionDownloadTask *task = [[NSURLSession sharedSession] downloadTaskWithRequest:request completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {

                // 请求完成,可以通知界面刷新界面等操作

                NSLog(@"第二步网络请求完成");

                

                // 使信号的信号量+1,这里的信号量本来为0,+1信号量为1(绿灯)

                dispatch_semaphore_signal(semaphore);

            }];

            

            [task resume];

            

            // 以下还要进行一些其他的耗时操作

            NSLog(@"耗时操作继续进行%@",[NSThread currentThread]);

            

            dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);

        });

        

        dispatch_group_notify(group, dispatch_get_main_queue(), ^{

            NSLog(@"刷新界面等在主线程的操作");

        });

    }

    打印信息:

    
    

    2020-03-25 11:43:16.034584+0800 GCD信号量Demo[14407:221514] 耗时操作继续进行<NSThread: 0x6000011f9a00>{number = 5, name = (null)}

    
    

    2020-03-25 11:43:16.034584+0800 GCD信号量Demo[14407:221513] 耗时操作继续进行<NSThread: 0x6000011d8400>{number = 6, name = (null)}

    
    

    2020-03-25 11:43:16.138100+0800 GCD信号量Demo[14407:221516] 第一步网络请求完成

    
    

    2020-03-25 11:43:22.544131+0800 GCD信号量Demo[14407:221515] 第二步网络请求完成

    
    

    2020-03-25 11:43:22.544268+0800 GCD信号量Demo[14407:221068] 刷新界面等在主线程的操作

     

    还有一种方法,设置依赖关系,这里我担心的就是,如果A,B请求出了问题,或者失败了,那C请求还会不会继续呢?

    参考https://www.cnblogs.com/tryFighting/p/8178376.html 

    NSOperationQueue * queue = [[NSOperationQueue alloc] init];
        NSBlockOperation * op1 = [NSBlockOperation blockOperationWithBlock:^{
    
            //block队列1
            [self _fetchBannerImageVoList];
        }];
        NSBlockOperation * op2 = [NSBlockOperation blockOperationWithBlock:^{
    
            //block队列2
            [self _fetchRemindData];
        }];
        NSBlockOperation * op3 = [NSBlockOperation blockOperationWithBlock:^{
    
            //block队列3
            [self _fetchMixArticleVideoData];
        }];
        [op2 addDependency:op1];
        [op3 addDependency:op2];
        [queue addOperation:op1];
        [queue addOperation:op2];
        [queue addOperation:op3];
    此文仅为鄙人学习笔记之用,朋友你来了,如有不明白或者建议又或者想给我指点一二,请私信我。liuw_flexi@163.com/QQ群:582039935. 我的gitHub: (学习代码都在gitHub) https://github.com/nwgdegitHub/
  • 相关阅读:
    欧拉公式
    isap的一些想法
    错误合集
    Hello World
    PAT (Advanced Level) Practice 1068 Find More Coins
    PAT (Advanced Level) 1087 All Roads Lead to Rome
    PAT (Advanced Level) 1075 PAT Judge
    PAT (Advanced Level) 1067 Sort with Swap(0, i)
    PAT (Advanced Level) 1017 Queueing at Bank
    PAT (Advanced Level) 1025 PAT Ranking
  • 原文地址:https://www.cnblogs.com/liuw-flexi/p/12564975.html
Copyright © 2011-2022 走看看