当前位置: 代码迷 >> 综合 >> iOS--GCD的常见用法,group、barrier、semaphore
  详细解决方案

iOS--GCD的常见用法,group、barrier、semaphore

热度:91   发布时间:2023-09-21 02:22:14.0

项目中用到了阿里云上传,有20张图片加3个音频加视频文件,用到了GCD的东西,总结了一下。

代码地址:https://github.com/SunshineTraveller/LMGCDTEST

凌晨五点了  直接上代码吧还是  有注释

总结:

 //   GCD 总结    /

 一、同步:1.1不区分串行或并发,和队列创建数目无关,都是在一个线程中执行。测试中任务在主线程中进行,会阻塞线程

 二、异步:2.1区分串行和并发

         2.1.1 串行:一个队列只会创建一个子线程,线程中的任务会按顺序依次执行,任务之间是有等待的,后面的任务会等前面的任务完成后再去执行,不会阻塞线程

              多个队列会创建多个子线程,每个线程的任务相对无序执行,任务之间没有等待,所有任务之间没有相互约束

         2.1.2 并发:和队列数无关,n个任务会创建n个子线程,所有任务之间没有等待,不存在相互约束

 三、组: group里的任务会在执行完后通过后通过通知回调(区分同步任务和异步任务!)

         3.1  group里执行的是同步任务(sync)

              dispatch_group_async(dispatch_group_t group,dispatch_queue_t queue,dispatch_block_t block);异步组函数里面的queue不能是串行队列类型(DISPATCH_QUEUE_SERIAL),否则不会执行,需为并发或者全局队列

         3.1.1 特点:group组会在放入group的队列里执行的任务会在全部任务执行完毕后通过dispatch_group_notify回调,告知外界group里的任务已经全部执行完毕,然后才会执行其他任务,group的队列会根据任务数创建对应的线程数,n个任务就会有n个线程,并且是按顺序执行的

         3.2  group里执行的是异步任务(async)

              !此时需要注意了,若为异步任务,若不做任何处理,所有任务的执行和通知会同时执行,需要添加 enter leave!这样才能达到group里的任务都执行完毕才会通知,然后执行其他任务

 四、 barrier:就像屏障一样,隔开屏障前后的任务

         4.1 dispatch_barrier_async 同步若同步执行队列,任务有序执行,且barrier后面的任务会在barrier前的任务执行完后才会去执行

         4.2 dispatch_barrier_sync 异步若异步执行队列,任务无序执行,会开启新线程且任务数多于线程数,barrier后面的任务会在barrier里的任务执行完后才会去执行

 五、信号量 semaphore记住一点即可!当信号总量 <0的时候,它的wait方法便会暂停,直到信号总量 >= 0的时候才会执行wait下面的方法,信号量增加的方法就是signal那个方法!

         dispatch_semaphore_wait:英文注释:Decrement the counting semaphore. If the resulting value is less than zero,this function waits for a signal to occur before returning.

                                大致翻译:减掉信号量的总数,若减去后的结果值小于0,则该函数在返回之前会等待一个信号发送

         keypoint: 1. dispatch_semaphore_wait函数会在信号量总数小于0的时候开始等待(tip:大于0则不会等待)wait后的所有任务都不会执行,直到信号量总数大于0。可以通过 dispatch_semaphore_signal 发送信号来增加信号量总数,一旦信号量总数大于0wait函数就会结束等待,后面的任务就会开始执行

 

 //


/**

 * 同步串行和队列数无关,不会开启新线程,会阻塞当前线程

 * 本次测试在主线程中

 */

- (IBAction)syncSerial:(id)sender {

    

    dispatch_queue_t sync_serial_queue  =dispatch_queue_create("sync_serial_queue",DISPATCH_QUEUE_SERIAL);

    dispatch_queue_t sync_serial_queue2 =dispatch_queue_create("sync_serial_queue2",DISPATCH_QUEUE_SERIAL);

    dispatch_queue_t sync_serial_queue3 =dispatch_queue_create("sync_serial_queue3",DISPATCH_QUEUE_SERIAL);

   

    dispatch_sync(sync_serial_queue, ^{

        

        [NSThreadsleepForTimeInterval:3];

        NSLog(@"syncSerial 1: ***  %@",[NSThreadcurrentThread]);

        

    });

    

    dispatch_sync(sync_serial_queue2, ^{

        

        [NSThreadsleepForTimeInterval:3];

        NSLog(@"syncSerial 2: ***  %@",[NSThreadcurrentThread]);

    });

    

    dispatch_sync(sync_serial_queue3, ^{

        

        [NSThreadsleepForTimeInterval:3];

        NSLog(@"syncSerial 3: ***  %@",[NSThreadcurrentThread]);

    });

    

    NSLog(@"syncSerial测试 ");

    

}

控制台:

2017-09-22 05:15:12.047 LMGCDTest[4937:384806] syncSerial 1: ***  <NSThread: 0x174265580>{number = 1, name = main}

2017-09-22 05:15:15.049 LMGCDTest[4937:384806] syncSerial 2: ***  <NSThread: 0x174265580>{number = 1, name = main}

2017-09-22 05:15:18.051 LMGCDTest[4937:384806] syncSerial 3: ***  <NSThread: 0x174265580>{number = 1, name = main}

2017-09-22 05:15:18.052 LMGCDTest[4937:384806] syncSerial 测试 



/** 

 * 同步并发不会开启新线程,会阻塞当前线程,任务不会同时开始

 */

- (IBAction)syncConcurrent:(id)sender {

    

    dispatch_queue_t sync_concurrent =dispatch_queue_create("sync_concurrent",DISPATCH_QUEUE_CONCURRENT);

    dispatch_queue_t sync_concurrent2 =dispatch_queue_create("sync_concurrent2",DISPATCH_QUEUE_CONCURRENT);

    dispatch_queue_t sync_concurrent3 =dispatch_queue_create("sync_concurrent3",DISPATCH_QUEUE_CONCURRENT);

    

    dispatch_sync(sync_concurrent, ^{

        NSLog(@"sync_concurrent 1: ***  %@",[NSThreadcurrentThread]);

        [NSThreadsleepForTimeInterval:3];

    });

    dispatch_sync(sync_concurrent2, ^{

        NSLog(@"sync_concurrent 2: ***  %@",[NSThreadcurrentThread]);

        [NSThreadsleepForTimeInterval:3];

    });

    dispatch_sync(sync_concurrent3, ^{

        NSLog(@"sync_concurrent 3: ***  %@",[NSThreadcurrentThread]);

        [NSThreadsleepForTimeInterval:3];

    });

    NSLog(@"sync_concurrent测试 ");

}


控制台:

2017-09-22 05:15:53.169 LMGCDTest[4954:385224] sync_concurrent 1: ***  <NSThread: 0x17407d800>{number = 1, name = main}

2017-09-22 05:15:56.171 LMGCDTest[4954:385224] sync_concurrent 2: ***  <NSThread: 0x17407d800>{number = 1, name = main}

2017-09-22 05:15:59.173 LMGCDTest[4954:385224] sync_concurrent 3: ***  <NSThread: 0x17407d800>{number = 1, name = main}

2017-09-22 05:16:02.175 LMGCDTest[4954:385224] sync_concurrent测试 




/** 

 *  异步串行一个队列只会创建一个线程,队列里的任务会按顺序执行(串行),不会阻塞线程

 *  异步串行 n个队列创建n个线程,各队列里的任务并发无序执行,不会阻塞线程

 */

- (IBAction)asyncSerial:(id)sender {

    

    dispatch_queue_t async_Serial =dispatch_queue_create("async_Serial",DISPATCH_QUEUE_SERIAL);

    dispatch_queue_t async_Serial2 =dispatch_queue_create("async_Serial2",DISPATCH_QUEUE_SERIAL);

    dispatch_queue_t async_Serial3 =dispatch_queue_create("async_Serial3",DISPATCH_QUEUE_SERIAL);

    

    dispatch_async(async_Serial, ^{

        [NSThreadsleepForTimeInterval:3];

        NSLog(@"async_concurrent 1: ***  %@",[NSThreadcurrentThread]);

    });

    dispatch_async(async_Serial2, ^{

        [NSThreadsleepForTimeInterval:3];

        NSLog(@"async_concurrent 2: ***  %@",[NSThreadcurrentThread]);

    });

    dispatch_async(async_Serial3, ^{

        [NSThreadsleepForTimeInterval:3];

        NSLog(@"async_concurrent 3: ***  %@",[NSThreadcurrentThread]);

    });

    NSLog(@"async_Serial测试 ");

    

}

控制台:

2017-09-22 05:17:22.529 LMGCDTest[4968:385500] async_Serial测试 

2017-09-22 05:17:25.531 LMGCDTest[4968:385714] async_concurrent 2: ***  <NSThread: 0x1702662c0>{number = 3, name = (null)}

2017-09-22 05:17:25.531 LMGCDTest[4968:385712] async_concurrent 1: ***  <NSThread: 0x174274a80>{number = 2, name = (null)}

2017-09-22 05:17:25.532 LMGCDTest[4968:385713] async_concurrent 3: ***  <NSThread: 0x170266dc0>{number = 4, name = (null)}




/** 

 * 异步并发

 * 和队列数无关,n个任务会创建n个线程,任务无序并发执行,不阻塞当前线程

 */

- (IBAction)asyncConcurrent:(id)sender {

    

    dispatch_queue_t asyncConcurrent =dispatch_queue_create("asyncConcurrent",DISPATCH_QUEUE_CONCURRENT);


    dispatch_async(asyncConcurrent, ^{

        [NSThreadsleepForTimeInterval:3];

        NSLog(@"asyncConcurrent 1: ***  %@",[NSThreadcurrentThread]);

    });

    dispatch_async(asyncConcurrent, ^{

        [NSThreadsleepForTimeInterval:3];

        NSLog(@"asyncConcurrent 2: ***  %@",[NSThreadcurrentThread]);

    });

    dispatch_async(asyncConcurrent, ^{

        

        [NSThreadsleepForTimeInterval:3];

        NSLog(@"asyncConcurrent 3: ***  %@",[NSThreadcurrentThread]);

    });

    NSLog(@"asyncConcurrent测试 ");

    

}

控制台:

2017-09-22 05:17:42.997 LMGCDTest[4968:385500] asyncConcurrent测试 

2017-09-22 05:17:46.003 LMGCDTest[4968:385754] asyncConcurrent 2: ***  <NSThread: 0x17426d2c0>{number = 6, name = (null)}

2017-09-22 05:17:46.003 LMGCDTest[4968:385753] asyncConcurrent 1: ***  <NSThread: 0x17026e900>{number = 5, name = (null)}

2017-09-22 05:17:46.005 LMGCDTest[4968:385755] asyncConcurrent 3: ***  <NSThread: 0x17426f200>{number = 7, name = (null)}





/* 

 * group里执行的是同步任务,并发按次序执行任务,每个任务都会在新线程中执行

 * group里的任务完成后会回调通知

 **/

- (IBAction)group:(id)sender {

    

    /* 1. group里执行的是同步任务 */

//    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

//    dispatch_queue_t queue = dispatch_queue_create("sieral_queue", DISPATCH_QUEUE_SERIAL);

    dispatch_queue_t queue =dispatch_queue_create("sieral_queue",DISPATCH_QUEUE_CONCURRENT);

    dispatch_queue_t queue1 =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

    

    dispatch_group_t group_t =dispatch_group_create();

    // 放在组中组中执行的都是同步任务

    dispatch_group_async(group_t, queue, ^{

       

        dispatch_sync(queue, ^{

            NSLog(@"group_sync task 1: %@",[NSThreadcurrentThread]);

            [NSThreadsleepForTimeInterval:3];

        });


    });

    dispatch_group_async(group_t, queue, ^{

        

        dispatch_sync(queue, ^{

            NSLog(@"group_sync task 2: %@",[NSThreadcurrentThread]);

            [NSThreadsleepForTimeInterval:3];

        });

        

    });

    dispatch_group_async(group_t, queue, ^{

        

        dispatch_sync(queue, ^{

            NSLog(@"group_sync task 3: %@",[NSThreadcurrentThread]);

            [NSThreadsleepForTimeInterval:3];

        });

        

    });

    // 前三个任务完成后再去执行其他任务

    dispatch_group_notify(group_t, queue1, ^{

        

        NSLog(@"前三个同步任务执行完毕收到通知,执行第四个,group_task 4: %@",[NSThreadcurrentThread]);

        [NSThreadsleepForTimeInterval:3];

        

    });

    

    NSLog(@"group sync Test");


}

控制台:

2017-09-22 05:18:06.217 LMGCDTest[4968:385500] group sync Test

2017-09-22 05:18:06.219 LMGCDTest[4968:385773] group_sync task 1: <NSThread: 0x174269640>{number = 8, name = (null)}

2017-09-22 05:18:06.220 LMGCDTest[4968:385786] group_sync task 2: <NSThread: 0x170276d40>{number = 9, name = (null)}

2017-09-22 05:18:06.221 LMGCDTest[4968:385787] group_sync task 3: <NSThread: 0x17026a340>{number = 10, name = (null)}

2017-09-22 05:18:09.227 LMGCDTest[4968:385787] 前三个同步任务执行完毕收到通知,执行第四个,group_task 4: <NSThread: 0x17026a340>{number = 10, name = (null)}




/**

 * group里执行的是异步任务,此时需要加进入enter’离开leave’组,否则通知回调会立即执行

 * 任务执行时enter 任务完成后leave

 * 若任务结束时不在当前方法内,设置group为全局变量即可

 */

- (IBAction)group_async:(id)sender {

    

    /** 2.group中执行的是异步任务,需要引入entreleave */

    dispatch_group_t group_t2 =dispatch_group_create();

    dispatch_queue_t queue_t2 =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

    dispatch_queue_t queue_t2_1 =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

    

    // 进入group_t2(进入组和离开组必须成对出现,否则会造成死锁)

    dispatch_group_enter(group_t2);

    // 组里的任务都是异步任务

    dispatch_group_async(group_t2, queue_t2, ^{

        

        dispatch_async(queue_t2, ^{

            NSLog(@"group_async Task1:  %@",[NSThreadcurrentThread]);

            [NSThreadsleepForTimeInterval:3];

            // 离开

            dispatch_group_leave(group_t2);

        });

        

    });

    

    dispatch_group_enter(group_t2);

    dispatch_group_async(group_t2, queue_t2, ^{

        

        dispatch_async(queue_t2, ^{

            NSLog(@"group_async Task2:  %@",[NSThreadcurrentThread]);

            [NSThreadsleepForTimeInterval:3];

            // 离开

            dispatch_group_leave(group_t2);

        });

        

    });

    dispatch_group_enter(group_t2);

    dispatch_group_async(group_t2, queue_t2, ^{

        

        dispatch_async(queue_t2, ^{

            NSLog(@"group_async Task3:  %@",[NSThreadcurrentThread]);

            [NSThreadsleepForTimeInterval:3];

            // 离开

            dispatch_group_leave(group_t2);

        });

        

    });

    

    // 组里的任务完成后通知

    dispatch_group_notify(group_t2, queue_t2_1, ^{

        

        NSLog(@"group_async Task4:  %@",[NSThreadcurrentThread]);

        [NSThreadsleepForTimeInterval:3];

        

    });

    

    NSLog(@"group asycn Test");

    

}

控制台:

2017-09-22 05:18:33.905 LMGCDTest[4968:385500] group asycn Test

2017-09-22 05:18:33.906 LMGCDTest[4968:385834] group_async Task1:  <NSThread: 0x17026e900>{number = 11, name = (null)}

2017-09-22 05:18:33.907 LMGCDTest[4968:385835] group_async Task2:  <NSThread: 0x174274340>{number = 12, name = (null)}

2017-09-22 05:18:33.908 LMGCDTest[4968:385836] group_async Task3:  <NSThread: 0x174263c80>{number = 13, name = (null)}

2017-09-22 05:18:36.913 LMGCDTest[4968:385836] group_async Task4:  <NSThread: 0x174263c80>{number = 13, name = (null)}






/**

 *  barrier 同步

 *  1.串行队列 任务在主线程中按序执行,会阻塞线程,barrier后的任务在barrier执行完后按序执行

 *  2.并发队列 任务在主线程中按序执行,会阻塞线程,barrier后的任务在barrier执行完后按序执行

 */

- (IBAction)sync_barrier:(id)sender {

    

//    dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);

    dispatch_queue_t queue =dispatch_queue_create("queue",DISPATCH_QUEUE_CONCURRENT);

    // 先执行的任务

    dispatch_sync(queue, ^{

        

        [NSThreadsleepForTimeInterval:3];

        NSLog(@"sync_barrier Task1: %@",[NSThreadcurrentThread]);

        

    });

    dispatch_sync(queue, ^{

        

        [NSThreadsleepForTimeInterval:3];

        NSLog(@"sync_barrier Task2: %@",[NSThreadcurrentThread]);

        

    });

    dispatch_sync(queue, ^{

        

        [NSThreadsleepForTimeInterval:3];

        NSLog(@"sync_barrier Task3: %@",[NSThreadcurrentThread]);

        

    });

    // 使用barrier阻断后面任务的执行

    dispatch_barrier_sync(queue, ^{

        NSLog(@"sync_barrier Task4: %@",[NSThreadcurrentThread]);

        [NSThreadsleepForTimeInterval:3];

    });

    // 后执行的任务

    dispatch_sync(queue, ^{

        [NSThreadsleepForTimeInterval:3];

        NSLog(@"sync_barrier Task5: %@",[NSThreadcurrentThread]);

    });

    dispatch_sync(queue, ^{

        [NSThreadsleepForTimeInterval:3];

        NSLog(@"sync_barrier Task6: %@",[NSThreadcurrentThread]);

    });

    NSLog(@"sync_barrier Test");

    

}

控制台:

2017-09-22 05:19:05.977 LMGCDTest[4968:385500] sync_barrier Task1: <NSThread: 0x174263d00>{number = 1, name = main}

2017-09-22 05:19:08.979 LMGCDTest[4968:385500] sync_barrier Task2: <NSThread: 0x174263d00>{number = 1, name = main}

2017-09-22 05:19:11.981 LMGCDTest[4968:385500] sync_barrier Task3: <NSThread: 0x174263d00>{number = 1, name = main}

2017-09-22 05:19:11.982 LMGCDTest[4968:385500] sync_barrier Task4: <NSThread: 0x174263d00>{number = 1, name = main}

2017-09-22 05:19:17.984 LMGCDTest[4968:385500] sync_barrier Task5: <NSThread: 0x174263d00>{number = 1, name = main}

2017-09-22 05:19:20.987 LMGCDTest[4968:385500] sync_barrier Task6: <NSThread: 0x174263d00>{number = 1, name = main}

2017-09-22 05:19:20.987 LMGCDTest[4968:385500] sync_barrier Test





/**

 *  barrier 异步

 *  串行队列下,会创建子线程,任务按序执行,在barrier执行后才会执行之后的任务

 *  并行队列下,会创建子线程,barrier之前的任务并发无序执行,barrier后的任务无序并发执行

 */

- (IBAction)async_barrier:(id)sender {

    

//    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);

//    dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);

    dispatch_queue_t queue =dispatch_queue_create("queue",DISPATCH_QUEUE_CONCURRENT);

    // 先执行的任务

    dispatch_async(queue, ^{

        

        [NSThreadsleepForTimeInterval:3];

        NSLog(@"async_barrier Task1: %@",[NSThreadcurrentThread]);

        

    });

    dispatch_async(queue, ^{

        

        [NSThreadsleepForTimeInterval:3];

        NSLog(@"async_barrier Task2: %@",[NSThreadcurrentThread]);

        

    });

    dispatch_async(queue, ^{

        

        [NSThreadsleepForTimeInterval:3];

        NSLog(@"async_barrier Task3: %@",[NSThreadcurrentThread]);

        

    });

    // 使用barrier阻断

    dispatch_barrier_async(queue, ^{

        NSLog(@"async_barrier Task4: %@",[NSThreadcurrentThread]);

        [NSThreadsleepForTimeInterval:3];

    });

    // 后执行的任务

    dispatch_async(queue, ^{

        [NSThreadsleepForTimeInterval:3];

        NSLog(@"async_barrier Task5: %@",[NSThreadcurrentThread]);

    });

    dispatch_async(queue, ^{

        [NSThreadsleepForTimeInterval:3];

        NSLog(@"async_barrier Task6: %@",[NSThreadcurrentThread]);

    });

    NSLog(@"async_barrier Test ");

    

}

控制台:

2017-09-22 05:19:46.713 LMGCDTest[4968:385500] async_barrier Test 

2017-09-22 05:19:49.717 LMGCDTest[4968:385944] async_barrier Task1: <NSThread: 0x170263100>{number = 14, name = (null)}

2017-09-22 05:19:49.719 LMGCDTest[4968:385945] async_barrier Task2: <NSThread: 0x17026b800>{number = 15, name = (null)}

2017-09-22 05:19:49.719 LMGCDTest[4968:385946] async_barrier Task3: <NSThread: 0x174269dc0>{number = 16, name = (null)}

2017-09-22 05:19:49.720 LMGCDTest[4968:385946] async_barrier Task4: <NSThread: 0x174269dc0>{number = 16, name = (null)}

2017-09-22 05:19:55.731 LMGCDTest[4968:385945] async_barrier Task6: <NSThread: 0x17026b800>{number = 15, name = (null)}

2017-09-22 05:19:55.731 LMGCDTest[4968:385946] async_barrier Task5: <NSThread: 0x174269dc0>{number = 16, name = (null)}





/**

 * 信号量

 * dispatch_semaphore_waitDecrement the counting semaphore. If the resulting value is less than zero,this function waits for a signal to occur before returning.

 * wait函数:减掉信号量的总数,若减去后的结果值小于0,则该函数在返回之前会等待一个信号发送

 *

 * keypoint: 1. dispatch_semaphore_wait函数会在信号量总数小于0的时候开始等待(tip:大于0则不会等待)wait后的所有任务都不会执行,直到信号量总数大于0。可以通过 dispatch_semaphore_signal 发送信号来增加信号量总数,一旦信号量总数大于0wait函数就会结束等待,后面的任务就会开始执行

 */

- (IBAction)semaphore:(id)sender {

    

    dispatch_queue_t queue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

    dispatch_async(queue, ^{

        

        // task1

        NSLog(@"task1 : %@",[NSThreadcurrentThread]);

        [NSThreadsleepForTimeInterval:3];

        NSLog(@"task1.1 : %@",[NSThreadcurrentThread]);

        

    });

    

    

    // 信号量创建

    dispatch_semaphore_t sema =dispatch_semaphore_create(0);

    NSLog(@"等待前 %@",sema);

    dispatch_async(queue, ^{

        

        // task2

        [NSThreadsleepForTimeInterval:10];

        NSLog(@"task2:  %@",[NSThreadcurrentThread]);

        NSLog(@"发信号 %@",sema);

        dispatch_semaphore_signal(sema);

    });

    

    

    // 等待

    dispatch_semaphore_wait(sema,DISPATCH_TIME_FOREVER);

   

    

    // 结束

    NSLog(@"等待后 %@",sema);

    dispatch_async(queue, ^{

        [NSThreadsleepForTimeInterval:3];

        NSLog(@"task3:  %@",[NSThreadcurrentThread]);

    });

    

    /*

     代码说明:

        代码一开始会创建总数为0的信号量,同时异步执行queue里的任务task1task2,接着执行dispatch_semaphore_wait函数,wait函数会使信号量-1,变成-1,由于-1<0 , wait函数开始等待,当然wait后面的代码是不会执行的。3秒后,task1任务执行完毕;task2里的任务会等10秒,然后执行dispatch_semaphore_signal发送了一个信号,signal会使信号量+1,这时信号量变成了0wait函数在监听到信号量变成非负数后便结束等待,继续执行wait函数后面的任务!

     */

}

控制台:

2017-09-22 05:20:18.634 LMGCDTest[4968:385500] 等待前 <OS_dispatch_semaphore: 0x174093d80>

2017-09-22 05:20:18.635 LMGCDTest[4968:385989] task1 : <NSThread: 0x17426fa00>{number = 17, name = (null)}

2017-09-22 05:20:21.640 LMGCDTest[4968:385989] task1.1 : <NSThread: 0x17426fa00>{number = 17, name = (null)}

2017-09-22 05:20:28.640 LMGCDTest[4968:385990] task2:  <NSThread: 0x17426fc00>{number = 18, name = (null)}

2017-09-22 05:20:28.641 LMGCDTest[4968:385990] 发信号 <OS_dispatch_semaphore: 0x174093d80>

2017-09-22 05:20:28.642 LMGCDTest[4968:385500] 等待后 <OS_dispatch_semaphore: 0x174093d80>

2017-09-22 05:20:31.650 LMGCDTest[4968:385990] task3:  <NSThread: 0x17426fc00>{number = 18, name = (null)}




/**

 创建了一个初使值为10semaphore,每一次for循环都会创建一个新的线程,线程结束的时候会发送一个信号,线程创建之前会信号等待,所以当同时创建了10个线程之后,for循环就会阻塞,等待有线程结束之后会增加一个信号才继续执行,如此就形成了对并发的控制,如上就是一个并发数为10的一个线程队列。

 */

- (IBAction)test:(id)sender {

    

    // semaphore 应用:可以控制并发量;可以使产生依赖

    // 控制并发量

    

//    dispatch_group_t group = dispatch_group_create();

//    dispatch_semaphore_t semaphore = dispatch_semaphore_create(10);

//    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

//    for (int i = 1; i < 101; i++)

//    {

//        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

//        

//        dispatch_group_async(group, queue, ^{

//            NSLog(@"  %i",i);

//            

//            // 请求路径

//            NSURL *url = [NSURL URLWithString:@"https://idmsa.apple.com/IDMSWebAuth/login?appIdKey=891bd3417a7776362562d2197f89480a8547b108fd934911bcbea0110d07f757&path=%2Faccount%2F&rv=1"];

            NSURL *url = [NSURL URLWithString:@"https://www.baidu.com"];

//            // 创建请求对象

//            NSURLRequest *reuqest = [[NSURLRequest alloc] initWithURL:url];

//            

//            // 发送请求

//            [NSURLConnection sendAsynchronousRequest:reuqest queue:[[NSOperationQueue alloc]init] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {

//                

//                // 请求成功,发送信号

//                dispatch_semaphore_signal(semaphore);

//                

//            }];

//            

//        });

//    }

//    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

    

    /*

    dispatch_queue_t global_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    // 创建一个信号总量为10的信号

    dispatch_semaphore_t sema = dispatch_semaphore_create(10);

    

    for (int i=1;i<101; i++) {

        

        // 每次执行循环前先执行wait,每次-110次后就变成0,第十一个及以后的任务会等待信号 >= 0

        dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);

        dispatch_async(global_queue, ^{

            // 请求路径

            NSURL *url = [NSURL URLWithString:@"https://idmsa.apple.com/IDMSWebAuth/login?appIdKey=891bd3417a7776362562d2197f89480a8547b108fd934911bcbea0110d07f757&path=%2Faccount%2F&rv=1"];

//            NSURL *url = [NSURL URLWithString:@"https://www.baidu.com"];

            // 创建请求对象

            NSURLRequest *reuqest = [[NSURLRequest alloc] initWithURL:url];

            NSLog(@"%d",i);

            // 发送请求

            [NSURLConnection sendAsynchronousRequest:reuqest queue:[[NSOperationQueue alloc]init] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {

                

                // 请求成功,发送信号

                dispatch_semaphore_signal(sema);

                

            }];

            

            

        });

        

    }

    */

    

    dispatch_queue_t global_queue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

    // 创建一个信号总量为10的信号

    dispatch_semaphore_t sema =dispatch_semaphore_create(10);

    

    for (int i=1;i<101; i++) {

        


        // 每次执行循环前先执行wait,每次-110次后就变成0,第十一个及以后的任务会等待信号 >= 0

        dispatch_semaphore_wait(sema,DISPATCH_TIME_FOREVER);

        dispatch_async(global_queue, ^{

            NSLog(@"当前任务编号 ---> %d",i);

            // 执行任务

            sleep(2);

            // 任务执行完毕,发送信号量

            dispatch_semaphore_signal(sema);

            

        });

        

    }

    

    

}

控制台:

2017-09-22 05:21:02.290 LMGCDTest[4968:386057] 当前任务编号 ---> 1

2017-09-22 05:21:02.290 LMGCDTest[4968:386056] 当前任务编号 ---> 2

2017-09-22 05:21:02.292 LMGCDTest[4968:386090] 当前任务编号 ---> 3

2017-09-22 05:21:02.293 LMGCDTest[4968:386091] 当前任务编号 ---> 4

2017-09-22 05:21:02.294 LMGCDTest[4968:386092] 当前任务编号 ---> 5

2017-09-22 05:21:02.295 LMGCDTest[4968:386093] 当前任务编号 ---> 6

2017-09-22 05:21:02.296 LMGCDTest[4968:386094] 当前任务编号 ---> 7

2017-09-22 05:21:02.297 LMGCDTest[4968:386095] 当前任务编号 ---> 8

2017-09-22 05:21:02.297 LMGCDTest[4968:386096] 当前任务编号 ---> 9

2017-09-22 05:21:02.298 LMGCDTest[4968:386097] 当前任务编号 ---> 10

2017-09-22 05:21:04.295 LMGCDTest[4968:386091] 当前任务编号 ---> 11

2017-09-22 05:21:04.295 LMGCDTest[4968:386056] 当前任务编号 ---> 12

2017-09-22 05:21:04.296 LMGCDTest[4968:386090] 当前任务编号 ---> 13

2017-09-22 05:21:04.296 LMGCDTest[4968:386057] 当前任务编号 ---> 14

2017-09-22 05:21:04.299 LMGCDTest[4968:386093] 当前任务编号 ---> 15

2017-09-22 05:21:04.299 LMGCDTest[4968:386092] 当前任务编号 ---> 16

2017-09-22 05:21:04.300 LMGCDTest[4968:386096] 当前任务编号 ---> 17

2017-09-22 05:21:04.300 LMGCDTest[4968:386095] 当前任务编号 ---> 18

2017-09-22 05:21:04.300 LMGCDTest[4968:386094] 当前任务编号 ---> 19

2017-09-22 05:21:04.303 LMGCDTest[4968:386097] 当前任务编号 ---> 20

这里截取了前20个,任务都是每次10个为一组开始执行



@end


参考文献:http://blog.csdn.net/zhonggaorong/article/details/51781654
  相关解决方案