GCD的基本概念和使用

1.多线程的同步,异步,串行,并行的区别和联系
同步:无论是串行还是并行,都按照主线程顺序执行;
异步:串行的时候顺序执行,并行的时候无序执行;
2.几个概念:
异步提交的任务立刻返回,在后台队列中执行 (自己的理解:提交任务后立即返回,一些耗时的操作在后台队列中执行,不阻塞)
同步提交的任务在执行完成后才会返回            (提交任务后,只有执行完成之后才能继续进行,阻塞)
并行执行(全局队列)提交到一个队列的任务,比如提交了任务1和任务2,在任务1开始执行,并且没有执行完毕时候,任务2就可以开始执行。
串行执行(用户创建队列) 提交到一个队列中的任务,比如提交了任务1和任务2,只有任务1结束后,任务2才可执行 
异步执行是两个队列之间的关系,并行执行是一个队列内部之间任务的关系
两个(多个)线程都要等待对方完成某个操作才能进行下一步,这时就会发生死锁。

3.在GCD中加入二个非常重要的概念: 任务队列
任务的执行方式分为二种: 1.同步执行2.异步执行。他们之间的区别是: 是否会创建新的线程
同步执行和异步执行的主要区别:同步执行(sync)会阻塞当前的线程并等待block中的任务执行完毕才会继续往下执行。异步执行(async)不会阻塞当前的线程,当前的线程直接往下执行。
队列 :用于存放任务。一共有两种队列,  串行队列  和  并行队列
串行队列: 串行队列 中的任务会根据队列的定义 FIFO 的执行,一个接一个的先进先出的进行执行。放到串行队列的任务,GCD 会 FIFO(先进先出) 地取出来一个,执行一个,然后取下一个,这样一个一个的执行。
并行队列:放到并行队列的任务,GCD 也会 FIFO的取出来,但不同的是,它取出来一个就会放到别的线程,然后再取出来一个又放到另一个的线程。这样由于取的动作很快,忽略不计,看起来,所有的任务都是一起执行的。不过需要注意,GCD 会根据系统资源控制并行的数量,所以如果任务很多,它并不会让所有任务同时执行
主队列这是一个特殊的 串行队列dispatch_queue_t queue =dispatch_get_main_queue();
自己可以创建 串行队列, 也可以创建 并行队列。它有两个参数,第一个队列的标识符,第二个才是最重要的。
第二个参数用来表示创建的队列是串行的还是并行的,传入 DISPATCH_QUEUE_SERIAL 或 NULL 表示创建串行队列。传入 DISPATCH_QUEUE_CONCURRENT 表示创建并行队列。例如:自己创建的并行队列 dispatch_queue_t concurrentQueue = dispatch_queue_create("com.bjsxt.concurrentQueue",DISPATCH_QUEUE_CONCURRENT);
全局并行队列:只要是并行任务一般都加入到这个队列。这是系统提供的一个并发队列。dispatch_queue_t defaultQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

具体的例子:
//    dispatch_queue_t mainQueue = dispatch_get_main_queue();
//    dispatch_sync(mainQueue,^{// (以为主线程是一个串行队列,线添加的代码先执行,而添加了一个同步的任务之后会阻塞到线程,等待同步任务里面都执行完之后在执行,所以造成互相等待,所以死锁)
//        NSLog(@"MainQueue");
//    });
//    dispatch_queue_t serialQueue = dispatch_queue_create("com.dullgrass.serialQueue", DISPATCH_QUEUE_SERIAL);
//    dispatch_sync(serialQueue, ^{   //该代码段后面的代码都不会执行,程序被锁定在这里
//        NSLog(@"会执行的代码");
//        dispatch_sync(serialQueue, ^{//两个(多个)线程都要等待对方完成某个操作才能进行下一步,这时就会发生死锁。将它放到block外面就能正常调用了
//            NSLog(@"代码不执行");
//        });
//    });
    
//    主线成
//    dispatch_queue_t mainQueue = dispatch_get_main_queue(); //因为是串行的所以按照顺序一个一个执行
//    dispatch_async(mainQueue, ^{
//        NSLog(@"1");
//        NSLog(@"11");
//        NSLog(@"111");
//        NSLog(@"1111");
//
//    });
//    dispatch_async(mainQueue, ^{
//        NSLog(@"2");
//    });
//    dispatch_async(mainQueue, ^{
//        NSLog(@"3");
//    });
//    dispatch_async(mainQueue, ^{
//        NSLog(@"4");
//    });
    全局并发线程
//    dispatch_queue_t defaultQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//    dispatch_async(defaultQueue, ^{ //因为是并发的所以无需的执行,但是block里面是顺序执行。如果都改成sync就是按照顺序执行的了
//        NSLog(@"g1");
//        NSLog(@"g11");
//        NSLog(@"g111");
//        NSLog(@"g1111");
//    });
//    dispatch_async(defaultQueue, ^{
//        NSLog(@"g2");
//    });
//    dispatch_async(defaultQueue, ^{
//        NSLog(@"g3");
//    });
//    dispatch_async(defaultQueue, ^{
//        NSLog(@"g4");
//    });
    
    //利用自定义队列可以模拟出 串行队列 并行队列 同步任务 异步任务
    //    同步:无论是串行还是并行,都按照主线程顺序执行;
    //    异步:串行的时候顺序执行,并行的时候无序执行;
    //    串行:无论同步还是异步都顺序执行
    //    并行:同步顺序执行,异步无序执行
//    自定义队列(在这因为是同步任务所以得等到block执行完毕之后才能进行下一步执行 NSLog(@"c6"); 但是如果改成async就会无序执行不会等待三秒,会先执行NSLog(@"c6");后执行NSLog(@"c5");)
//    自己创建的并行队列DISPATCH_QUEUE_CONCURRENT、串行队列DISPATCH_QUEUE_SERIAL(NULL)
    dispatch_queue_t concurrentQueue = dispatch_queue_create("com.bjsxt.concurrentQueuess", NULL);
    dispatch_async(concurrentQueue, ^{//在这里要是改成sync 就会按照顺序一个一个执行下去 等待线程睡眠之后再执行
        NSLog(@"c4");
        dispatch_async(concurrentQueue, ^{//串行队列--这个改成sync会死锁,以为是串行队列,要等待异步任务里面都执行之后在执行其他的,而又因为同步的任务添加到里面,5要等待6执行完成之后在执行,而6又要等待5执行完成之后执行,从而造成死锁现象。
            [NSThread sleepForTimeInterval:3];
            NSLog(@"c5");
        });
        NSLog(@"c6");
    });
    dispatch_sync(concurrentQueue, ^{//如果改成sync,同步。。这样的话就会阻塞当前的线程(concurrentQueue),必须等到他执行完之后才能向下执行
        NSLog(@"c7");//NSLog(@"c7")这个相当于是任务的执行代码,就是把打印的这句话放到concurrentQueue这个线程中去执行
    });
    dispatch_async(concurrentQueue, ^{
        NSLog(@"c8");
        
    });
    dispatch_async(concurrentQueue, ^{
        NSLog(@"c9");
        
    });
   
    //1.创建队列组
    dispatch_group_t group = dispatch_group_create();
    //2.创建队列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    //3.多次使用队列组的方法执行任务, 只有异步方法,没有同步方法
    //3.1.执行3次循环
    dispatch_group_async(group, queue, ^{
        for (NSInteger i = 0; i < 3; i++) {
            NSLog(@"group-01 - %@", [NSThread currentThread]);
        }
    });
    
    //3.2.主队列执行8次循环
    dispatch_group_async(group, dispatch_get_main_queue(), ^{
        for (NSInteger i = 0; i < 8; i++) {
            NSLog(@"group-02 - %@", [NSThread currentThread]);
        }
    });
    
    //3.3.执行5次循环
    dispatch_group_async(group, queue, ^{
        for (NSInteger i = 0; i < 5; i++) {
            NSLog(@"group-03 - %@", [NSThread currentThread]);
        }
    });
    
    //4.都完成后会自动通知
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"完成 - %@", [NSThread currentThread]);
    });
    
    //延迟执行
    // 创建队列
    dispatch_queue_t queueG = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    // 设置延时,单位秒
    double delay = 5;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), queueG, ^{
        // 3秒后需要执行的任务
        NSLog(@"延迟执行操作");
    });
//    我们都知道在其他线程操作完成后必须到主线程更新UI。所以,介绍完所有的多线程方案后,我们来看看有哪些方法可以回到主线程。
    //Objective-C
//    [self performSelectorOnMainThread:@selector(run) withObject:nil waitUntilDone:NO];

GitHub地址https://github.com/yaoqiGetHub/OCDispatchQueueDemo



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值