Swift3 GCD的基本用法(一) - 任务和队列、服务优先级、信号量

Swift3 GCD的基本用法(一) - 任务和队列、服务优先级、信号量,第1张

概述本文代码:https://github.com/NinoWang/MultithreadingDemo/tree/master 多线程的知识,网上有无数文章来讲述,但真正理解起来还是有点绕的,还是要靠实践才能真正理解,本文以代码为主,少量叙述为辅和大家来捋一下。建议直接下载源码进行理解,不理解的地方在来文章里找答案。话少说,开捋。 基本概念 说到GCD,通常与相似功能的Operation Queu

本文代码:https://github.com/NinoWang/MultithreadingDemo/tree/master


多线程的知识,网上有无数文章来讲述,但真正理解起来还是有点绕的,还是要靠实践才能真正理解,本文以代码为主,少量叙述为辅和大家来捋一下。建议直接下载源码进行理解,不理解的地方在来文章里找答案。话少说,开捋。


基本概念

说到GCD,通常与相似功能的Operation Queue进行比较理解。

GCD是使用C语言构成的API,而Operation Queue是具体的Objc对象;GCD是使用block的形式管理队列中的任务,而Operation Queue是直接把队列和任务作为具体的对象进行 *** 作。


任务和队列

任务分为同步任务(sync)和异步任务(async)两种。

两者的区别在于,异步任务具备开辟新线程的能力,而同步任务不具备该能力。


队列是执行任务的容器,遵循先进先出(FIFO)的原则,GCD中队列分为串行队列(Serial dispatch Queue)和并发队列(Concurrent dispatch Queue)两种。

两者的区别在于,并发队列可以同时执行多个任务(自动开启多个线程),而串行队列只能按顺序逐个执行任务。

另外还有两个特殊的子分类的队列:全局队列(global queue)和主队列(main queue)。

全局队列:并发队列的一种,用来执行较耗时的 *** 作。

主队列:串行队列的一种,只能在主线程中进行,只有主线程空闲的时候才能被执行,用来刷新UI


可以说GCD中所有场景都是围绕两种任务和两种队列来实现的,不同任务和队列的排列组合:




并发队列异步任务
func conAsync() {        let concurrentQueue = dispatchQueue(label: "Concurrent",attributes: .concurrent)        for i in 0...10 {            concurrentQueue.async {                print("this is NO.\(i),current thread name is \(Thread.current)")            }        }    }

结果为无序

串行队列异步任务
func serAsync() {        let serialQueue = dispatchQueue(label: "Serial")        for i in 0...10 {            serialQueue.async {                print("this is NO.\(i),current thread name is \(Thread.current)")            }        }    }

结果为有序

主队列异步任务
func mainAsync() {        let mainQueue = dispatchQueue.main        for i in 0...10 {            mainQueue.async {                print("this is NO.\(i),current thread name is \(Thread.current)")            }        }    }

结果为有序

全局队列异步任务
func globalAsync() {        let globalQueue = dispatchQueue.global()        for i in 0...10 {            globalQueue.async {                print("this is NO.\(i),current thread name is \(Thread.current)")            }        }    }

结果为无序

并发队列同步任务
func conSync() {        let concurrentQueue = dispatchQueue(label: "Concurrent",attributes: .concurrent)        for i in 0...10 {            concurrentQueue.sync {                print("this is NO.\(i),current thread name is \(Thread.current)")            }        }    }

结果为有序

串行队列同步任务
func serSync() {        let serialQueue = dispatchQueue(label: "Serial")        for i in 0...10 {            serialQueue.sync {                print("this is NO.\(i),current thread name is \(Thread.current)")            }        }    }

结果为有序

主队列同步任务
func mainSync() {        let mainQueue = dispatchQueue.main        for i in 0...10 {            mainQueue.sync {                print("this is NO.\(i),current thread name is \(Thread.current)")            }        }    }

死锁造成程序假死

全局队列同步任务
func globalSync() {        let globalQueue = dispatchQueue.global()        for i in 0...10 {            globalQueue.sync {                print("this is NO.\(i),current thread name is \(Thread.current)")            }        }    }

结果为有序

线程间通讯-从子线回到主线程

iOS开发中,主线程主要用来处理UI层面的任务,诸如:点击、拖拽、滚动等。而比较耗时的任务则放到子线程中,诸如:数据请求、文件下载上传等。这个时候就需要使用到线程之间的通讯。

let globalQueue = dispatchQueue.global()                globalQueue.async {            if let url = URL.init(string: "https://placebeard.it/200/150") {                do {                    let imageData = try Data(contentsOf: url)                    let image = UIImage(data: imageData)                                        dispatchQueue.main.async {                        self.imgVIEw.image = image                        self.imgVIEw.sizetoFit()                    }                                    } catch {                    print(error)                }            }                    }
服务优先级(Qos)

这里的服务优先级决定了对一个任务分配资源的大小,并非绝对的执行顺序。swift3中Qos共有6个级别,优先级从高到低依次为userInteractive、userInitiated、default、utility、background、unspecifIEd。

func QoS() {        // 优先级从高到低 userInteractive、userInitiated、default、utility、background、unspecifIEd        // 指定Qos 这里分别用三种方式指定        // 方式1        let userInteractiveQueue = dispatchQueue(label: "userInteractive",qos: .userInteractive)        let defaultQueue = dispatchQueue(label: "default",qos: .default)        let conQueue = dispatchQueue(label: "con",attributes: .concurrent)        for i in 0...5 {            userInteractiveQueue.async {                print("userInteractive ====> \(i)")            }                        defaultQueue.async {                print("defaultQueue ====> \(i)")            }                        // 方式2            dispatchQueue.global(qos: .unspecifIEd).async {                print("unspecifIEd ====> \(i)")            }            dispatchQueue.global(qos: .userInitiated).async {                print("userInitiated ====> \(i)")            }                        // 方式3            conQueue.async(qos: .utility) {                print("utility ====> \(i)")            }            conQueue.async(qos: .background) {                print("background ====> \(i)")            }        }    }
信号量(semaphore)

先看下百度百科的描述信号量的例子:

以一个停车场的运作为例。简单起见,假设停车场只有三个车位,一开始三个车位都是空的。这时如果同时来了五辆车,看门人允许其中三辆直接进入,然后放下车拦,剩下的车则必须在入口等待,此后来的车也都不得不在入口处等待。这时,有一辆车离开停车场,看门人得知后,打开车拦,放入外面的一辆进去,如果又离开两辆,则又可以放入两辆,如此往复。

在这个停车场系统中,车位是公共资源,每辆车好比一个线程,看门人起的就是信号量的作用。

简单来说,信号量起到对多线程调用资源的监管作用。

dispatchSemaphore(value:):用于创建信号量,可以指定初始化信号量计数值,这里我们默认1

semaphore.wait():会判断信号量,如果为1,则往下执行。如果是0,则等待。

semaphore.signal():代表运行结束,信号量加1,有等待的任务这个时候才会继续执行。

func semaphore() {        let semaphore = dispatchSemaphore(value: 1)        for i in 0...10 {            dispatchQueue.global().async {                semaphore.wait()                print("\(i)")                                semaphore.signal()            }        }    }

续篇:Swift3 GCD的基本用法(二) - 队列的循环/挂起/恢复、其他常用方法

@H_601_419@ 总结

以上是内存溢出为你收集整理的Swift3 GCD的基本用法(一) - 任务和队列、服务优先级、信号量全部内容,希望文章能够帮你解决Swift3 GCD的基本用法(一) - 任务和队列、服务优先级、信号量所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1055357.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-25
下一篇 2022-05-25

发表评论

登录后才能评论

评论列表(0条)

保存