zoukankan      html  css  js  c++  java
  • GCD信号量semaphore控制线程并发数

    GCD提供了信号semaphore来控制线程并发数,提供一下三个函数

    dispatch_semaphore_create(<#long value#>) // 创建信号semaphore,value参数为任务并发同时执行时线程最大并发数

    dispatch_semaphore_wait(<#dispatch_semaphore_t  _Nonnull dsema#>, <#dispatch_time_t timeout#>) // 信号阻塞,信号发送后->判断是否有空闲的计数可用,如果有可用计数执行后面的任务,如果没有可用计数就让当前线程阻塞

    dispatch_semaphore_signal(<#dispatch_semaphore_t  _Nonnull dsema#>) // 信号发送,信号发送后->通知有空闲的计数可用,其他阻塞的任务就可以执行

     

        dispatch_semaphore_t semaphore = dispatch_semaphore_create(2);
        
        dispatch_group_t group = dispatch_group_create();
        
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        
        for (int i=0; i<20; i++) {  // for 20次,每次创建一个线程执行任务,当线程任务达到2个后,创建任务就会被阻塞,至到有任务完成并signal后,wait等待线程才会解除阻塞,继续被执行
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            dispatch_group_async(group, queue, ^{
                NSLog(@"%zd ---%@",i,[NSThread currentThread]);
                [NSThread sleepForTimeInterval:0.2];
                dispatch_semaphore_signal(semaphore);
            });
        }
        
        dispatch_group_wait(group, 4); // group任务等待4秒,如果group所有任务任务4秒还未执行完成,执行下面任务
        
        dispatch_group_notify(group, queue, ^{
            NSLog(@"dispatch_group_notify"); // group内任务全部执行完毕,通知回调
        });
        
        NSLog(@"semaphore end...");
        
        2017-09-02 20:31:53.611 GCD测试[16021:328482] 0 ---<NSThread: 0x600000275780>{number = 7, name = (null)}
        2017-09-02 20:31:53.611 GCD测试[16021:329153] 1 ---<NSThread: 0x608000263b40>{number = 10, name = (null)}
        2017-09-02 20:31:53.885 GCD测试[16021:328482] 2 ---<NSThread: 0x600000275780>{number = 7, name = (null)}
        2017-09-02 20:31:53.885 GCD测试[16021:329153] 3 ---<NSThread: 0x608000263b40>{number = 10, name = (null)}
        2017-09-02 20:31:54.152 GCD测试[16021:328482] 4 ---<NSThread: 0x600000275780>{number = 7, name = (null)}
        2017-09-02 20:31:54.152 GCD测试[16021:329153] 5 ---<NSThread: 0x608000263b40>{number = 10, name = (null)}
        2017-09-02 20:31:54.400 GCD测试[16021:329153] 6 ---<NSThread: 0x608000263b40>{number = 10, name = (null)}
        2017-09-02 20:31:54.400 GCD测试[16021:328482] 7 ---<NSThread: 0x600000275780>{number = 7, name = (null)}
        2017-09-02 20:31:54.601 GCD测试[16021:329153] 8 ---<NSThread: 0x608000263b40>{number = 10, name = (null)}
        2017-09-02 20:31:54.601 GCD测试[16021:328482] 9 ---<NSThread: 0x600000275780>{number = 7, name = (null)}
        2017-09-02 20:31:54.801 GCD测试[16021:329153] 10 ---<NSThread: 0x608000263b40>{number = 10, name = (null)}
        2017-09-02 20:31:54.801 GCD测试[16021:328482] 11 ---<NSThread: 0x600000275780>{number = 7, name = (null)}
        2017-09-02 20:31:55.069 GCD测试[16021:329153] 13 ---<NSThread: 0x608000263b40>{number = 10, name = (null)}
        2017-09-02 20:31:55.069 GCD测试[16021:328482] 12 ---<NSThread: 0x600000275780>{number = 7, name = (null)}
        2017-09-02 20:31:55.270 GCD测试[16021:328482] 14 ---<NSThread: 0x600000275780>{number = 7, name = (null)}
        2017-09-02 20:31:55.270 GCD测试[16021:329153] 15 ---<NSThread: 0x608000263b40>{number = 10, name = (null)}
        2017-09-02 20:31:55.470 GCD测试[16021:329153] 17 ---<NSThread: 0x608000263b40>{number = 10, name = (null)}
        2017-09-02 20:31:55.470 GCD测试[16021:328482] 16 ---<NSThread: 0x600000275780>{number = 7, name = (null)}
        2017-09-02 20:31:55.711 GCD测试[16021:328215] semaphore end...
        2017-09-02 20:31:55.711 GCD测试[16021:328482] 18 ---<NSThread: 0x600000275780>{number = 7, name = (null)}
        2017-09-02 20:31:55.711 GCD测试[16021:329153] 19 ---<NSThread: 0x608000263b40>{number = 10, name = (null)}
        2017-09-02 20:31:55.912 GCD测试[16021:329153] dispatch_group_notify

    经测试信号量设置为2,但是任务开启的任务线程有时可能为3个,这个不是说信号量不起作用,3表示并发线程2个,但是线程使用完后,下次2个同时并发时可能会开启新的线程,也有可能直接使用上次并发完的线程

     

    示例:

     

    __block BOOL isok = NO;
    
    dispatch_semaphore_t sema = dispatch_semaphore_create(0);
    EventEngine *engine = [[EventEngine alloc] init];
    [engine engineCompletion:^(BOOL isOpen) {
        isok = isOpen;
        dispatch_semaphore_signal(sema);
    } onError:^(int errorCode, NSString *errorMessage) {
        isok = NO;
        dispatch_semaphore_signal(sema);
    }];
    
    dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
    // 等待engine有结果后才解除阻塞
    
    // do other task
    

      

     

  • 相关阅读:
    io系列浅谈
    git 删除分支--本地分支和远程分支
    提问须知
    PDF 补丁丁 0.6.2.3691 测试版发布
    PDF 补丁丁 0.6.2.3689 测试版发布
    .Net调用接口处理时间过长,前端访问超时解决方案
    Abp用多个DbContext
    IDEA 报错 Could not autowire. No beans of 'UserMapper' type found(无法自动装配。找不到类型为 'UserMapper' 的 bean)解决IDEA中自动装配,找不到类型的bean问题
    springboot整合springmvc拦截器
    springboot自动配置原理
  • 原文地址:https://www.cnblogs.com/HJiang/p/7467752.html
Copyright © 2011-2022 走看看