Swift3 GCD的基本用法(一) - 任务和队列、服务优先级、信号量
本文代码: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的基本用法(二) - 队列的循环/挂起/恢复、其他常用方法 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |