GCD的基本概念和使用

来源:互联网 发布:中国突破第一岛链 知乎 编辑:程序博客网 时间:2024/06/13 21:31
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



1 0
原创粉丝点击