iOS

iOS多线程:【GCD】】详尽总结

2018-05-30  本文已影响13人  老黑来袭

此篇文章只是自学照别人抄的

iOS多线程:『GCD』详尽总结 - 简书

1.GCD简介

什么是GCD

GCD是 Apple开发的一个多核编程的较新的解决方案。它主要用于优化应用程序以支持多核处理器以及其他堆成多处理系统。他是一个在线程池模式的基础上执行的并发任务。

为什么要用GCD?

GCD 可用于多核的并行运算

GCD会自动利用更多的CPU内核(比如双核、四核)

GCD会自动管理县城的生命周期(创建线程、调度任务、销毁线程)

程序员只需要告诉GCD想要执行什么任务,不需要编写任何线程管理代码

2.GCD任务和队列

学习GCD之前先来了解GCD中两个核心概念:任务和队列。

任务:就是执行操作的意思,换句话说就是你在线程中执行的那段代码。在GCD中是放在Block中的。执行任务有两种方式:同步执行(sync)和异步执行(async)。两这的主要区别是:时都等待队列的任务执行结束,以及是否具备开创新线程的能力

同步执行(sync):

同步添加任务到指定的队列中,再添加的任务执行结束之前,会一直等待知道队列里面的任务完成之后再继续执行。

只能在当前线程中执行任务,不具备开启新线程能力

异步执行(async):

异步添加任务到指定的队列中,他不会做任何等待,可以继续执行任务。

可以在新的线程中执行任务,具备开启新线程的能力。

队列:(Dispatch Q)这里的队列指执行任务的等待队列,即用来存放任务的队列。队列是一种特殊的线性表,采用FIFO的原则即新任务总是被插入队尾。

在GCD中有两种队列:串行队列和并发队列。两者都一样

串行队列:每次只有一个任务被执行

并行队列:可以让多个任务(同时)执行。可以开启多个线程但是根据任务类型来判断

队列:就是任务执行的地方。是栈,为什么是栈,因为栈符合先进先出原则,可以控制任务执行顺序

GCD 的使用步骤

只需要两步

1创建一个队列

2追加任务到队列里

队列的创建方法

可以使用 dispatch_queue_create 来创建队列,需要传入两个参数,第一个参数是队列的唯一标识,用于我们方便Debug,可为空。第二个参数是用来识别串行队列还是并行队列,DISPATCH_QUEUE_SERIAL 标示串行队列DISPATCH_QUEUE_CONCURRENT表示并发队列

对于串行队列GCD提供了一个特殊的并行队列DISPATCH_GET_MAIN_QUEUE

对于并发队列GCD默认提供了全局并发队列DISPATCH_GET_GOLOBAL_QUEUE

他有两个参数第一个参数标示队列优先级 , 第二个参数暂时不用

任务的创建方法

同步任务的创建

dispatch_sync(queue, cal)

异步任务的创建

dispatch_async(queue,cal)

接下来是组合网上有很多我直接说结果

1同步任务

2异步任务

A串行队列

B并行队列

C主队列

1+A任务不会创建新的线程

1+B任务不会创建新的线程

1+C任务在主队列执行 死锁

2+A任务会创建线程但串行执行

2+B任务会创建线程

2+C不会创建线程在主队列执行

线程间通信

dispatch_get_main_queue

栅栏方法

dispatch_barrier_async

我们有时需要异步执行两组操作,而且第一组操作执行完之后,才能开始执行第二组操作。这样我们就需要一个相当于栅栏一样的一个方法将两组异步执行的操作组给分割起来,当然这里的操作组里可以包含一个或多个任务。这就需要用到dispatch_barrier_async方法在两个操作组间形成栅栏。

dispatch_barrier_async函数会等待前边追加到并发队列中的任务全部执行完毕之后,再将指定的任务追加到该异步队列中。然后在dispatch_barrier_async函数追加的任务执行完毕之后,异步队列才恢复为一般动作,接着追加任务到该异步队列并开始执行。具体如下图所示:

GCD延时执行方法

dispatch_after

我们经常会遇到这样的需求:在指定时间(例如3秒)之后执行某个任务。可以用 GCD 的dispatch_after函数来实现。

需要注意的是:dispatch_after函数并不是在指定时间之后才开始执行处理,而是在指定时间之后将任务追加到主队列中。严格来说,这个时间并不是绝对准确的,但想要大致延迟执行任务,dispatch_after函数是很有效的。

一次性代码

dispatch

我们在创建单例、或者有整个程序运行过程中只执行一次的代码时,我们就用到了 GCD 的 dispatch_once 函数。使用

dispatch_once 函数能保证某段代码在程序运行过程中只被执行1次,并且即使在多线程的环境下,dispatch_once也可以保证线程安全。

GCD 快速迭代方法

dispatch_apply

通常我们会用 for 循环遍历,但是 GCD 给我们提供了快速迭代的函数dispatch_apply。dispatch_apply按照指定的次数将指定的任务追加到指定的队列中,并等待全部队列执行结束。

如果是在串行队列中使用dispatch_apply,那么就和 for 循环一样,按顺序同步执行。可这样就体现不出快速迭代的意义了。

我们可以利用并发队列进行异步执行。比如说遍历 0~5 这6个数字,for 循环的做法是每次取出一个元素,逐个遍历。dispatch_apply可以 在多个线程中同时(异步)遍历多个数字。

还有一点,无论是在串行队列,还是异步队列中,dispatch_apply 都会等待全部任务执行完毕,这点就像是同步操作,也像是队列组中的dispatch_group_wait方法。

GCD 队列组

dispatch_group

有时候我们会有这样的需求:分别异步执行2个耗时任务,然后当2个耗时任务都执行完毕后再回到主线程执行任务。这时候我们可以用到 GCD 的队列组。

调用队列组的dispatch_group_async先把任务放到队列中,然后将队列放入队列组中。或者使用队列组的dispatch_group_enter、dispatch_group_leave组合 来实现

dispatch_group_async。

调用队列组的dispatch_group_notify回到指定线程执行任务。或者使用dispatch_group_wait回到当前线程继续向下执行(会阻塞当前线程)。

6.5.1 dispatch_group_notify

GCD信号量

上一篇 下一篇

猜你喜欢

热点阅读