GCD信号量的应用

目录

一、关于信号量

二、应用

准备

1、控制并发数

2、顺序请求接口GCD

3、顺序请求接口NSOperationQueue

三、注意事项


一、关于信号量

信号量的主要作用是通过阻塞线程来控制流程顺序。

主要有三个函数:

dispatch_semaphore_t sem = dispatch_semaphore_create(0) :创建信号量

dispatch_semaphore_signal(sem) :信号量+1

dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER) : 信号量-1

当信号量为0时执行wait操作会阻塞线程,等到信号量大于0才继续执行。

二、应用

准备

写两个网络请求方法,方便以下应用例子中使用:

- (void)requestTest1Success:(void(^)(BOOL isSuccess))result
{
    NSString * urlStr = @"http://121.8.145.4:10096/app_if/getConfig?appID=1";
    
    AFHTTPSessionManager * manager = [AFHTTPSessionManager manager];
    // 超时时间
    manager.requestSerializer.timeoutInterval = 30;
    // 上传的格式(JSON)
    manager.requestSerializer = [AFHTTPRequestSerializer serializer];//普通格式
    manager.requestSerializer = [AFJSONRequestSerializer serializer];//json格式
    manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"text/html",@"text/plain", nil];
    
    
    [manager GET:urlStr parameters:nil progress:^(NSProgress * _Nonnull downloadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
        result(YES);
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        result(NO);

        
    }];
}
- (void)requestTest2Success:(void(^)(BOOL isSuccess))result
{
    NSString * urlStr = @"http://121.8.145.4:10096/app_if/getConfig?appID=1";
    
    AFHTTPSessionManager * manager = [AFHTTPSessionManager manager];
    // 超时时间
    manager.requestSerializer.timeoutInterval = 30;
    // 上传的格式(JSON)
    manager.requestSerializer = [AFHTTPRequestSerializer serializer];//普通格式
    manager.requestSerializer = [AFJSONRequestSerializer serializer];//json格式
    manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"text/html",@"text/plain", nil];
    
    
    [manager GET:urlStr parameters:nil progress:^(NSProgress * _Nonnull downloadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
        result(YES);
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        NSLog(@" -- test 2-- fail -- %@",error);
        
        result(NO);

    }];
}

1、控制并发数

dispatch_semaphore_t sem = dispatch_semaphore_create(2);
    dispatch_queue_t queue = dispatch_queue_create("queue", NULL);
    for (int i=0; i<10; i++) {
        
        dispatch_async(queue, ^{
            [self requestTest1Success:^(BOOL isSuccess) {
                NSLog(@" === %d",i);
                dispatch_semaphore_signal(sem);
            }];
            dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
            NSLog(@" -- test --");
        });
        
    }

设定信号量为2,总任务数为10,当前两个任务在完成时,其他任务是阻塞的,只有完成其中一个才能继续开始第三个任务,依次类推,可以实现并发数的控制,在遇到多图加载之类的情况时可以进行并发数控制。

2、顺序请求接口GCD

 dispatch_group_t group = dispatch_group_create();
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    dispatch_semaphore_t sem = dispatch_semaphore_create(0);
    
    dispatch_group_async(group, queue, ^{
        
        [self requestTest1Success:^(BOOL isSuccess) {
            sleep(2);
            NSLog(@" -- test 1--");
            dispatch_semaphore_signal(sem);
        }];
        dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
        
        [self requestTest2Success:^(BOOL isSuccess) {
            
            NSLog(@" -- test 2--");
            dispatch_semaphore_signal(sem);
            
        }];
        dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
        
    });
  
    
    dispatch_group_notify(group, queue, ^{
        
       NSLog(@" -- test 3--");
    });

执行结果顺序执行test1,test2,最后执行test3。

执行test1时进行线程阻塞,只是请求完成以后signal信号量+1,才能继续执行下面的任务。

应用场景为:需要顺序执行某些请求,请求结束以后在执行其他操作,通过group和信号量结合操作来实现。

3、顺序请求接口NSOperationQueue

 dispatch_semaphore_t sem = dispatch_semaphore_create(0);
    
    NSOperationQueue * queue = [[NSOperationQueue alloc]init];
    NSBlockOperation * op1 = [NSBlockOperation blockOperationWithBlock:^{
        
        [self requestTest1Success:^(BOOL isSuccess) {
            sleep(2);
            NSLog(@" -- test 1--");
            dispatch_semaphore_signal(sem);
        }];
        dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
    }];
    
    NSBlockOperation * op2 = [NSBlockOperation blockOperationWithBlock:^{

        [self requestTest2Success:^(BOOL isSuccess) {
            
            NSLog(@" -- test 2--");
            dispatch_semaphore_signal(sem);
            
        }];
        dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
        
    }];
    [op2 addDependency:op1];
    
    [queue addOperations:@[op1,op2] waitUntilFinished:NO];

用NSOperationQueue可以同样实现。

不过在顺序执行请求的时候,waitUntilFinished 设置成 YES 会阻塞线程,所以需要请求完成以后在执行其他任务时,推荐使用GCD。

三、注意事项

需要注意的是文中的例子是请求接口,afn请求接口会出现新的线程,而dispatch_group在发送请求的时候就表示该任务已经完成,并不能等到接口返回成功,所以需要用信号量来控制,如果是普通的业务逻辑处理就不需要了。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值