iOS开发GCD

有关任务和队列的概念在此就不多说了,我的简书有详细记载,上一篇是基础,这一篇是针对-----GCD。

一、初识GCD

  1. 全称:Grand Central Dispatch
  2. GCD是Apple开发的一个多核编程的方法,主要用于优化应用程序,支持多核处理器,其他对称多处理系统。它是一个在线程池模式的基础上执行的并发任务。
  3. GCD可以用于多核的并行运算,会自动利用更多的CPU内核,会自动管理线程的生命周期,我们只需告诉GCD我们要执行的任务,不需编写任何线程管理代码。

二、GCD的使用

  1. 创建一个队列(串行、并行)
  2. 将任务追加到任务的等待队列中,然后系统会根据任务类型执行任务(同步、异步)
1.创建队列
/*
  1.com.xhh.test:参数是队列的唯一标识符,用于DEBUG,可为空
  2.DISPATCH_QUEUE_SERIAL:串行队列
  3.DISPATCH_QUEUE_CONCURRENT:并行队列
  4.dispatch_get_main_queue:获取主队列(Main Dispatch Queue),所有放在主队列的任务都会放到主线程中执行
  5.dispatch_get_global_queue:获取全局队列(Global Dispatch Queue),参数2个队列优先级和0
*/
// 创建串行队列
dispatch_queue_t queue = dispatch_queue_create("com.xhh.test", DISPATCH_QUEUE_SERIAL); 
// 创建并行队列
dispatch_queue_t queue = dispatch_queue_create("com.xhh.test", DISPATCH_QUEUE_CONCURRENT);
// 获取主队列
dispatch_queue_t queue = dispatch_get_main_queue();
// 获取全局队列(并行)
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
2.任务的创建(同步、异步)
/*
两种特殊队列:全局队列和主队列(详细的在我的简书文章中有详细讲解,有想了解的小伙伴可以去学习,一定要先看上一篇文章,才有基础更容易理解这篇文章)
*/
// 同步
dispatch_sync(queue, ^{
  // 要执行的任务代码
});
// 异步
dispatch_sync(queue, ^{
  // 要执行的任务代码
});

三、同步主队列

在主线程中使用同步执行 + 主队列,追加到主线程的任务都不再执行了,在XCode 9上还会报崩溃。这是为什么呢?
这是因为我们在主线程中执行syncMain方法,相当于把syncMain任务放到了主线程的队列中。而同步执行会等待当前队列中的任务执行完毕,才会接着执行。那么当我们把任务追加到主队列中,任务就在等待主线程处理完syncMain任务。而syncMain任务需要等待任务执行完毕,才能接着执行。
那么,现在的情况就是syncMain任务和任务都在等对方执行完毕。这样大家互相等待,所以就卡住了,所以我们的任务执行不了。
如果不在主线程调用呢?
在其他线程调用同步执行主队列

// 使用 NSThread 的 detachNewThreadSelector 方法会创建线程,并自动启动线程执行
 selector 任务
[NSThread detachNewThreadSelector:@selector(syncMain) toTarget:self withObject:nil];

在其他线程中使用同步执行 + 主队列可看到:
所有任务都是在主线程(非当前线程)中执行的,没有开启新的线程(所有放在主队列中的任务,都会放到主线程中执行)。
所有任务都在打印的syncConcurrent---begin和syncConcurrent---end之间执行(同步任务需要等待队列的任务执行结束)。
任务是按顺序执行的(主队列是串行队列,每次只有一个任务被执行,任务一个接一个按顺序执行)。
为什么现在就不会卡住了呢?
因为syncMain 任务放到了其他线程里,而任务都在追加到主队列中,这个任务都会在主线程中执行。syncMain 任务在其他线程中执行到追加任务到主队列中,因为主队列现在没有正在执行的任务,所以,会直接执行主队列的任务,等任务执行完毕,再接着执行其他任务。所以这里不会卡住线程。

四、GCD线程间的通信

在iOS开发过程中,一般在主线程进行UI刷新(点击、滚动、拖拽等事件),耗时操作放在子线程中,如下载图片,文件上传等。从子线程回到主线程进行操作,这就是线程之间的通信。可以看到在其他线程中先执行任务,执行完了之后回到主线程执行主线程的相应操作。

// 获取全局并发队列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
    // 获取主队列
    dispatch_queue_t mainQueue = dispatch_get_main_queue(); 
    
    dispatch_async(queue, ^{
        // 异步追加任务
        for (int i = 0; i < 2; ++i) {
            [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
            NSLog(@"1---%@",[NSThread currentThread]);      // 打印当前线程
        }
        
        // 回到主线程
        dispatch_async(mainQueue, ^{
            // 追加在主线程中执行的任务
            [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
            NSLog(@"2---%@",[NSThread currentThread]);      // 打印当前线程
        });
    });

五、GCD的其他方法

  1. GCD栅栏方法----------------dispatch_barrier_async
  2. GCD延迟执行方法----------dispatch_after
  3. GCD只执行一次-------------dispatch_once
  4. GCD快速迭代方法----------dispatch_apply
  5. GCD队列组-------------------dispatch_group
  6. GCD信号量-------------------dispatch_semaphore

参考文章:
iOS 多线程:『GCD』详尽总结

猜你喜欢

转载自blog.csdn.net/weixin_33720956/article/details/87084414