iOS GCD随笔

- (void)viewDidLoad {

    [super viewDidLoad];

    // Do any additional setup after loading the view, typically from a nib.

    

#warning 1.队列概念

    

    // FIFO队列 :即先进先出

    // 不管是串行队列(SerialQueue)还是并发队列(ConcurrentQueue),都是FIFO队列。也就意味着,任务一定是一个一个地,按照先进先出的顺序来执行。

    

    // 串行队列:在创建队列时,传参数DISPATCH_QUEUE_SERIAL表示创建串行队列。任务会一个一个地执行,只有前一个任务执行完成,才会继续执行下一个任务。串行执行并不是同步执行的意思,一定要注意区分

    

    // 并发队列:在创建队列时,传参数DISPATCH_QUEUE_CONCURRENT表示创建并发队列。并发队列会尽可能多地创建线程去执行任务。并发队列中的任务会按入队的顺序执行任务,但是哪个任务先完成是不确定的。

 

#warning 2.队列类型

//    1.全局队列:苹果预定义的全局并发队列,只能通过苹果提供的API来获取,可以设置优先级。

//    2.主队列:在应用启动的时候,就会自动创建与主线程关联的串行队列,我们也可能获取,不能手动创建。

//    3.手动创建串行队列

//    4.手动创建并发队列

    

#warning 3.死锁(Deadlock)

    // 所谓死锁(Deadlock)是指它们都卡住了,并等待对方完成或执行其它操作。第一个不能完成是因为它在等待第二个的完成。但第二个也不能完成,因为它在等待第一个的完成。

    

#warning 4.获取公共队列

    // dispatch_get_current_queue:在iOS 6.0之后已经废弃,用于获取当前正在执行任务的队列,主要用于调试

    // dispatch_get_main_queue: 最常用的,用于获取应用主线程关联的串行调度队列

    // dispatch_get_global_queue:最常用的,用于获取应用全局共享的并发队列

    

#warning 5.控制并发数

    // 太多并发是会带来很多的风险的。在实际开发中,并不是并发数越多就越好,往往是需要控制其并发数量的。比如,在处理网络请求发数时,通常会设置限制最大并发数为4左右。当并发数量大了,开销也会很大。学过操作系统应该清楚,并发量大了,临界资源访问操作就很难控制,控制不好就会导致死锁等。当我们需要执行循环异步处理任务时,可以考虑使用dispatch_apply来替代

    

    // 例如:

    // 获得全局并发queue

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

//    size_t gcount = 10;

//    dispatch_apply(gcount, gqueue, ^(size_t i) {

//        [self uploadImageWithIndex:(NSUInteger)(i)];

//    });

//    

//    - (void)uploadImageWithIndex:(NSUInteger)imageIndex {

//        NSLog(@"上传索引为%lu的图片", imageIndex);

//    }

    

//    打印结果说明顺序是不确定的,可看得出来这是并发执行的:

//    2015-11-24 00:06:11.692 TestGCD[27714:2678984] 上传索引为0的图片

//    2015-11-24 00:06:11.692 TestGCD[27714:2679067] 上传索引为3的图片

//    2015-11-24 00:06:11.692 TestGCD[27714:2678984] 上传索引为4的图片

//    2015-11-24 00:06:11.692 TestGCD[27714:2679064] 上传索引为2的图片

//    2015-11-24 00:06:11.692 TestGCD[27714:2678984] 上传索引为6的图片

//    2015-11-24 00:06:11.692 TestGCD[27714:2679065] 上传索引为1的图片

//    2015-11-24 00:06:11.693 TestGCD[27714:2678984] 上传索引为8的图片

//    2015-11-24 00:06:11.692 TestGCD[27714:2679067] 上传索引为5的图片

//    2015-11-24 00:06:11.693 TestGCD[27714:2679064] 上传索引为7的图片

//    2015-11-24 00:06:11.693 TestGCD[27714:2679065] 上传索引为9的图片

//    

//    注意:dispatch_apply或dispatch_apply_f函数也是在所有迭代完成之后才会返回,因此这两个函数会阻塞当前线程。当我们在主线程中使用时,一定要小心,很容易造成事件无法响应,所以如果循环代码需要一定的时间执行,可考虑在另一个线程中调用这两个函数。如果所传递的参数是串行queue,而且正是执行当前代码的queue,就会产生死锁。

    

    

    

    /****************************************************************************************/

    /****************************************************************************************/

    /****************************************************************************************/

    /****************************************************************************************/

    /****************************************************************************************/

    /****************************************************************************************/

    /****************************************************************************************/

    

    

    [self GCDTest1]; // 全局队列

    

    [self GCDTest15]; // 全局队列优先级

    

    [self GCDTest14]; // 全局队列优先级测试

    

    [self GCDTest4]; // 主队列

    

    [self GCDTest2]; // 创建串行队列

    

    [self GCDTest3]; // 创建并发队列

    

    [self GCDTest5]; // 串行子队列优先级

    

    [self GCDTest6]; // 并行子队列优先级

    

}

- (void)GCDTest1

{

    // 全局队列不需要创建, 只需要直接获取就可以了 例如

    // 参数1:优先级, 参数2:苹果预留的,现在还没使用到

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

    

    

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        NSLog(@"1");

    });

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        sleep(2);

        NSLog(@"2");

    });

    

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        sleep(1);

        NSLog(@"3");

    });

    // 任务1是直接执行,任务2是在异步执行过程中被睡眠2秒,任务3在异步执行过程中被睡眠1秒,结果任务3先于任务2执行完成。说明并发执行任务并不需要等待其他任务先执行完。对于这三个任务,是互不干扰的

    

}

- (void)GCDTest2

{

    // 参数1:一个C语言的字符串,是队列的标签,也就是名称,通常是采用com..这样的格式

    // 参数2:是指定串行队列还是并发队列 (串行:DISPATCH_QUEUE_SERIAL 并发:DISPATCH_QUEUE_CONCURRENT)

    dispatch_queue_t serialQueue = dispatch_queue_create("com.Mmmz.serial-queue",

                                                         DISPATCH_QUEUE_SERIAL);

    // 添加任务到调度队列

    dispatch_async(serialQueue, ^{

        NSLog(@"串行1");

    });

    // 添加任务到调度队列

    dispatch_async(serialQueue, ^{

        sleep(2);

        NSLog(@"串行2");

    });

    // 添加任务到调度队列

    dispatch_async(serialQueue, ^{

        sleep(1);

        NSLog(@"串行3");

    });

    // 从打印结果可以看出来,任务全在同一个线程中执行,但是并不是在主线程,而是在子线程执行。不过任务执行只有顺序地执行,任务没有执行完毕之前,下一个任务是不能开始的。

}

- (void)GCDTest3

{

    dispatch_queue_t serialQueue = dispatch_queue_create("com.Mmmz.concurrent-queue",

                                                         DISPATCH_QUEUE_CONCURRENT);

    dispatch_async(serialQueue, ^{

        NSLog(@"并行1");

    });

    dispatch_async(serialQueue, ^{

        sleep(2);

        NSLog(@"并行2");

    });

    dispatch_async(serialQueue, ^{

        sleep(1);

        NSLog(@"并行3");

    });

    // 从打印结果可以看出来,任务在三个子线程中执行,且互不干扰,不需要等待其他任务完成,就可以并发地分别去执行!

}

- (void)GCDTest4

{

    dispatch_async(dispatch_get_main_queue(), ^{

        sleep(2);

        NSLog(@"main 1");

    });

    

    dispatch_async(dispatch_get_main_queue(), ^{

        NSLog(@"main 2");

    });

    

    dispatch_async(dispatch_get_main_queue(), ^{

        sleep(1);

        NSLog(@"main 3");

    });

    // 从打印结果可看到执行的顺序是按入队的顺序来执行的。虽然让任务1睡眠2秒再执行,其他任务也只能等待任务1完成,才能继承执行任务2,在任务2执行完成,才能执行任务3。 主线程是串行的.

}

- (void)GCDTest5

{

    // 通过dispatch_set_target_queue将串行队列设置成全局队列的子队列, 全局队列可以设置优先级, 所以子队列也会跟着目标队列有了优先级

    

    // 创建一个串行队列

    dispatch_queue_t serialQueue = dispatch_queue_create("com.Mmmz.serial-queue", DISPATCH_QUEUE_SERIAL);

    // 将这个串行队列的目标队列设置成全局队列, 并设置全局队列优先级

    dispatch_set_target_queue(serialQueue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0));

    dispatch_async(serialQueue, ^{

        NSLog(@"111");

    });

    dispatch_async(serialQueue, ^{

        NSLog(@"222");

    });

    dispatch_async(serialQueue, ^{

        NSLog(@"333");

    });

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        NSLog(@"444");

    });

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        NSLog(@"555");

    });

    

//    我们把串行队列放到了优先级为LOW的全局队列中,另外还把任务4、5放到优先级为DEFAULT的全局队列中,所以优先执行任务4、5,最后才执行优先级为低的串行队列中的任务。

//    所以这里设置了优先级后,队列就不一定是按FIFO规则了,出队的顺序就变成了按优先级了。只有当所有的任务都是同一个优先级的情况下,才是FIFO。

}

- (void)GCDTest6

{

    // 思路与串行队列优先级一样

    

    // 创建一个并行队列

    dispatch_queue_t concurrentQueue = dispatch_queue_create("com.Mmmz.concurrency-queue", DISPATCH_QUEUE_CONCURRENT);

    // 将这个并行队列的目标队列设置成全局队列, 并设置全局队列优先级

    dispatch_set_target_queue(concurrentQueue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0));

    dispatch_async(concurrentQueue, ^{

        NSLog(@"11111111");

    });

    dispatch_async(concurrentQueue, ^{

        NSLog(@"22222222");

    });

    dispatch_async(concurrentQueue, ^{

        NSLog(@"33333333");

    });

    dispatch_async(concurrentQueue, ^{

        NSLog(@"44444444");

    });

    dispatch_async(concurrentQueue, ^{

        NSLog(@"55555555");

    });

    dispatch_async(concurrentQueue, ^{

        NSLog(@"66666666");

    });

    dispatch_async(concurrentQueue, ^{

        NSLog(@"77777777");

    });

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        NSLog(@"88888888");

    });

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        NSLog(@"99999999");

    });

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        NSLog(@"!!!!!!!!");

    });

    

    // 打印结果 88888 99999 !!!!!! 肯定先执行, 之后是剩下的

    

    // 并发队列执行任务的顺序是不确定的。对于同一优先级的任务,他们出队的顺序一定是FIFO,先进先出,但是先执行的顺序是不确定的!

}

- (void)GCDTest14

{

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{

        sleep(1);

        NSLog(@"全局4");

    });

    

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{

        sleep(3);

        NSLog(@"全局3");

    });

    

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        sleep(2);

        NSLog(@"全局2");

    });

    

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{

        sleep(5);

        NSLog(@"全局1");

    });

    

    // 打印结果可以看出 优先级只是执行的优先级, 即哪个先执行, 并不是哪个先执行完

}

- (void)GCDTest15

{

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{

        NSLog(@"全局4");

    });

    

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{

        NSLog(@"全局3");

    });

    

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        NSLog(@"全局2");

    });

    

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{

        NSLog(@"全局1");

    });

    

    // 优先级由高到低 DISPATCH_QUEUE_PRIORITY_HIGH > DISPATCH_QUEUE_PRIORITY_DEFAULT > DISPATCH_QUEUE_PRIORITY_LOW > DISPATCH_QUEUE_PRIORITY_BACKGROUND

}

posted @ 2016-04-08 16:15  枫锅锅  阅读(136)  评论(0编辑  收藏  举报