代码改变世界

iOS-多线程dispatch_semaphore_t dispatch_queue_t dispatch_group_t常见用法场景

2018-05-23 18:31  菜鸟Alex  阅读(1205)  评论(0编辑  收藏  举报
  • dispatch_semaphore_t 用法,dispatch_semaphore_create 创建信号量实际就是创建的对象设置最大并发数.不得小于0, 小于0导致崩溃,dispatch_semaphore_wait , 减少一个信号量, 比如创建的对象信号量是5, wait一次就减少一个信号量,信号量变为4, 当信号量为0的时候当前线程就会等待,直到信号量>0的时候才会往下进行.dispatch_semaphore_signal 增加一个信号量,减少与增加信号量是成对出现的.
dispatch_semaphore_t semap = dispatch_semaphore_create(1); // 控制最大并发数1条新线程 此时下面操作是线程安全的
dispatch_semaphore_wait(semap, DISPATCH_TIME_FOREVER);// 此时信号量由1 变为 0 ,即使下面有任务也不会再执行, 因为信号量为0
// 单个线程操作区域... 线程安全
dispatch_semaphore_signal(semap);
  • 第一种常见用法 group + queue 使用场景: 单次, 多个任务同时执行, 自动开启多个线程,最后执行完毕在回调处理执行完毕的结果
  • 缺点: 不能控制最大并发数, 操作同一资源不安全

// DISPATCH_QUEUE_CONCURRENT 生成一个并发队列(可以有多条线程)
    dispatch_queue_t queue = dispatch_queue_create("sendrequest", DISPATCH_QUEUE_CONCURRENT);
    // 创建group
    dispatch_group_t group = dispatch_group_create();
// 多个耗时任务同时进行 加入group中同时进行,执行完毕监听回调
    dispatch_group_async(group, queue, ^{
        NSLog(@"1");
        sleep(2);
        NSLog(@"1+");
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"2");
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"3");
    });

    // group任务全部执行完毕回调
    dispatch_group_notify(group, queue, ^{
        NSLog(@"done");
    });

  • 第二种使用场景 semaphore + queue 场景: 多次(有100个任务需要执行, 例如数据库100条数据,需要上传,每条创建一个任务,开2个线程), 控制最大并发数(后台开2个线程), group中不能控制最大并发数, 操作数据线程加锁,保证线程安全
  • 缺点不能处理回调

    dispatch_semaphore_t semap = dispatch_semaphore_create(2); // 控制最大并发数2条新线程
    // DISPATCH_QUEUE_CONCURRENT 生成一个并发队列(可以有多条线程)
    dispatch_queue_t queue = dispatch_queue_create("sendrequest", DISPATCH_QUEUE_CONCURRENT);
    // 10个任务, 最大并发2, 
    for (int i = 0; i < 10; i++) {
        dispatch_async(queue, ^{
                dispatch_semaphore_wait(semap, DISPATCH_TIME_FOREVER);
                // 线程操作区域
                 dispatch_semaphore_signal(semap);
            });
    }

  • 第三种场景组合用法: dispatch_semaphore_t(设置最大并发数) + dispatch_queue_t(创建并发队列) + dispatch_group_t(监听任务完成回调) 可以处理任务完成回调, 可设置最大并发数

dispatch_semaphore_t semap = dispatch_semaphore_create(2); // 控制最大并发数2条新线程
    // DISPATCH_QUEUE_CONCURRENT 生成一个并发队列(可以有多条线程)
    dispatch_queue_t queue = dispatch_queue_create("sendrequest", DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_t group = dispatch_group_create();
    
    for (int i = 0; i < 10; i++) {
        dispatch_group_async(group, queue, ^{
            dispatch_semaphore_wait(semap, DISPATCH_TIME_FOREVER);
            // 线程操作区域 最多有两个线程在此做事情
            dispatch_semaphore_signal(semap);
        });
    }
     // group任务全部执行完毕回调
    dispatch_group_notify(group, queue, ^{
        NSLog(@"done");
    });