swift详解之十六-----------GCD基础部分

GCD基础部分

注:本节主要详细讲解线程同步的一些基本概念和GCD基础部分



GCD (Grand Central Dispatch)

首先我们来了解处理线程中的一些基本概念 :

  • 串行:同时只能有一个任务被执行
  • 并发:同时可以有多个任务执行
  • 同步:同步任务会阻塞当前线程,知道任务完成
  • 异步:预定的任务会完成但不会等它完成,因此,一个异步函数不会阻塞当前线程去执行下一个函数。
  • 临界区:就是一段代码不能被并发执行,也就是,两个线程不能同时执行这段代码。(不同代码去操作共享资源可能会变质)
  • 死锁:多个线程卡住了 , 并等待对方完成或执行其它操作。第一个不能完成是因为它在等待第二个的完成。但第二个也不能完成,因为它在等待第一个的完成。
  • 线程安全:线程安全的代码能在多线程或并发任务中被安全的调用,而不会导致任何问题
  • 上下文切换:一个上下文切换指当你在单个进程里切换执行不同的

    线程时存储与恢复执行状态的过程。这个过程在编写多任务应用时很普遍,但会带来一些额外的开销

  • 并发与并行:并发代码的不同部分可以“同步”执行。多核设备通过并行来同时执行多个线程;为了使单核设备也能实现这一点,它们必须先运行一个线程,执行一个上下文切换,然后运行另一个线程或进程。这通常发生地足够快以致给我们并发执行地错觉
  • Queues 队列:GCD 提供有 dispatch queues 来处理代码块,这些队列管理你提供给 GCD 的任务并用 FIFO(先进先出) 顺序执行这些任务。所有的调度队列(dispatch queues)自身都是线程安全的,你能从多个线程并行的访问它们。当你了解了调度队列如何为你自己代码的不同部分提供线程安全后,GCD的优点就是显而易见的。关于这一点的关键是选择正确类型的调度队列和正确的调度函数来提交你的工作。由于在串行队列中不会有两个任务并发运行,因此不会出现同时访问临界区的风险;相对于这些任务来说,这就从竞态条件下保护了临界区。所以如果访问临界区的唯一方式是通过提交到调度队列的任务,那么你就不需要担心临界区的安全问题了。
  • Concurrent Queues 并发队列:在并发队列中的任务能得到的保证是它们会按照被添加的顺序开始执行,但这就是全部的保证了。任务可能以任意顺序完成,你不会知道何时开始运行下一个任务,或者任意时刻有多少 Block 在运行。这完全取决于 GCD 。

    如果一个 Block 的执行时间与另一个重叠,也是由 GCD 来决定是否将其运行在另一个不同的核心上,如果那个核心可用,否则就用上下文切换的方式来执行不同的 Block 。

  • Queue Types 队列类型:首先,系统提供给你一个叫做 主队列(main queue) 的特殊队列。和其它串行队列一样,这个队列中的任务一次只能执行一个。然而,它能保证所有的任务都在主线程执行,而主线程是唯一可用于更新 UI 的线程。这个队列就是用于发生消息给 UIView 或发送通知的。

系统同时提供给你好几个并发队列。它们叫做 全局调度队列(Global Dispatch Queues) 。目前的四个全局队列有着不同的优先级:background、low、default 以及 high。要知道,Apple 的 API 也会使用这些队列,所以你添加的任何任务都不会是这些队列中唯一的任务。

最后,你也可以创建自己的串行队列或并发队列。这就是说,至少有五个队列任你处置:主队列、四个全局调度队列,再加上任何你自己创建的队列。GCD 的“艺术”归结为选择合适的队列来调度函数以提交你的工作。

下面看下示例

Global Dispatch Queues

 let back = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
        let defual = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        let high = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
        let low = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);

        dispatch_async(back) {
            //后台执行
        }
        dispatch_async(defual) {
            //后台执行
        }
        dispatch_async(low) {
            //后台执行
        }
        dispatch_async(high) {
            //后台执行
        }

上面是全局后台执行的几种类型。可以设定级别

下面看看主线程。多用来刷新UI

        dispatch_async(dispatch_get_main_queue()) {
            //主线程执行
        }

用户队列

 let queue = dispatch_queue_create("myQueue", nil);
        dispatch_async(queue) {
            //后台执行
        }

下面是延时执行

  let time = NSEC_PER_SEC*3
        let popTime = dispatch_time(DISPATCH_TIME_NOW, Int64(time))
        print(NSEC_PER_SEC)
        dispatch_after(popTime,dispatch_get_main_queue()) {
            //这里的内容在3秒后执行
            print(2)
        }
        print(1)

这里NSEC_PER_SEC = 1000000000

先输出1 三秒后输出2

dispatch_once 在单例模式中很有用哦 , 不用if判断。加上这个就能保证 只执行一次了

 func onlyOnce(){
        struct Static {
            static var onceToken : dispatch_once_t = 0
        }
        dispatch_once(&Static.onceToken) {
            print("只会输出一次哦")
        }
        print("多次输出呀")
    }

这里static变量保证用的是同一个token

         onlyOnce()
        onlyOnce()
        onlyOnce()
        onlyOnce()
        onlyOnce()

然后我们多次调用 。

只会输出一次哦
多次输出呀
多次输出呀
多次输出呀
多次输出呀
多次输出呀

dispatch_once中的代码只执行了一次 。

以上就是今天总结的GCD基础部分 。下次总结下高级部分

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-12-23 05:46:35

swift详解之十六-----------GCD基础部分的相关文章

swift详解之十四 -----------NSThread 异步下载图片

NSThread 异步下载图片 在IOS中处理多线程有三个方案 , NSThread .NSOperation .GCD .当然GCD应该是最方便的 ,我们一个一个学 .先理解底层的,最后再使用最方便的 . NSThread: 优点:NSThread 比其他两个轻量级 缺点:需要自己管理线程的生命周期,线程同步.线程同步对数据的加锁会有一定的系统开销 我们先研究下用NSThread 异步加载网络图片 : NSThread有两种创建方式 ,一种是通过实例方法.一种是通过类方法. let threa

swift详解之十-------------异常处理、类型转换 ( Any and AnyObject )

异常处理.类型转换 ( Any and AnyObject ) 1.错误处理 (异常处理) swift 提供第一类错误支持 ,包括在运行时抛出 ,捕获 , 传送和控制可回收错误.在swift中 ,错误用复合 ErrorType 协议的值表示 . Swift枚举把一系列相关的错误组合在一起.同时可以把一些相关的值和错误关联在一起 . 因此 编译器会为实现ErrorType协议的Swift枚举类型自动实现相应的合成 这里看个很简单的小例子. enum WrongName:ErrorType{ cas

swift详解之十二-----------------泛型

泛型 注:本文详细讲解泛型,对写一些公共方法,共用的东西的时候很有帮助.想成为一个优秀的程序员吗?这个必须掌握 泛型代码可以让你写出根据自我需求定义.适用于任何类型的,灵活可重用的函数和类型. 下面直接看一个简单的示例 , 泛型其实就是在写的时候不指定是哪种类型 , 只有再用得时候才指定类型 ,这些类型可以给一些限定.例如 Array Dictionary 等 写一个简单的交换数据的方法,不限定类型 func swapTwoValue<T>(inout a:T,inout _ b:T){ le

swift详解之十九--------------UITableView的基本操作(下拉刷新,新增删除,分组,检索等)

UITableView的基本操作(下拉刷新,新增删除,分组,检索等) 注:本小结总结UITableview的一些基本用法 UITbleView继承自UIScrollView,只能用来显示一列数据(目前就只认识到这里),纵向滑动. 一般有两种方式来实现,直接用UITableViewController , 占满整个屏幕 .不用手动实现UITableViewDataSource 和UITableViewDelegate .另一种方式在UIViewController 中.我们看看这种方式 let t

swift详解之十八------------ScrollView

ScrollView 注:本小节详细介绍scrollView的用法 UIScrollView是一个能够滚动的视图控件,可以用来展示大量的内容,并且可以通过滚动查看所有的内容 UIScrollView的用法,将需要展示的内容添加到UIScrollView中 设置UIScrollView的contentView属性,告诉UIScrollView所有内容的尺寸 let scroll = UIScrollView(); scroll.backgroundColor = UIColor.grayColor

swift详解之十五------------NSThread线程同步锁

NSThread线程同步锁 上小节用NSThread实现读取网络图片 , 这节用NSThread 模拟一个卖票的例子 .用NSLock 或者NSCondition 锁定资源 var total = 100 //总票数 var w1 = 0 //窗口1卖出票数 var w2 = 0 //窗口2卖出票数 var isSell = true //是否出售 var lock:NSLock? var condition:NSCondition? 这里首先定义一些变量 然后再点击卖票的时候,开启连个线程模仿

Nginx详解二十六:Nginx架构篇之性能优化

一.性能优化考虑点 1.当前系统结构瓶颈 通过压力测试观察指标.日志检测.性能分析 2.了解业务模式 接口业务类型.系统层次化结构 3.性能与安全 二.ab接口压力测试工具 1.安装:yum -y install httpd-tools 2.使用: ad -n 2000 -c 2 http://127.0.0.1-n:总的请求数-c:并发数-k:是否开始长连接 准备环境 检查语法,并重载nginx -tc /etc/nginx/nginx.conf nginx -s reload -c /etc

C#面向接口编程详解(1)——思想基础

我想,对于各位使用面向对象编程语言的程序员来说,"接口"这个名词一定不陌生,但是不知各位有没有这样的疑惑:接口有什么用途?它和抽象类有什么区别?能不能用抽象类代替接口呢?而且,作为程序员,一定经常听到"面向接口编程"这个短语,那么它是什么意思?有什么思想内涵?和面向对象编程是什么关系?本文将一一解答这些疑问. 1.面向接口编程和面向对象编程是什么关系 首先,面向接口编程和面向对象编程并不是平级的,它并不是比面向对象编程更先进的一种独立的编程思想,而是附属于面向对象思

苹果新的编程语言 Swift 语言进阶(十六)--泛化

泛化允许你定义一个宽松.可重用的函数或者类型,使用泛化能够避免代码的重复,也能以更清楚和抽象的方式来表达程序的意图. 泛化是Swift语言提供的强大功能之一,Swift提供的许多标准库都使用了泛化来创建,如Swift提供的数组和词典类型.通过使用泛化,你能使用一个数组和词典来包含和存储任何类型的元素. 1.1 泛化函数 使用Swift语言你能定义一个可以工作于任意类型的泛化函数,从而不必为每种类型都定义一个具有相同功能的函数,这样就可以大大减少代码的重复. 如对一个实现任意类型值交换(swap)