3、GCD-swift

作者: Laughingg | 来源:发表于2016-06-21 09:29 被阅读14997次

GCD 一直以来是基于 c 语言的。
apple 为了使 GCD 使用更加的 swift 化。 对 GCD 进行了进行了改造。
以下所有代码都是基于 Swift3.0


先来段废话:
(不了解基本概念的建议看看, 了解的直接略过!)

GCD

Grand Central Dispatch (GCD)是Apple开发的一个多核编程的较新的解决方法。它主要用于优化应用程序以支持多核处理器以及其他对称多处理系统。它是一个在线程池模式的基础上执行的并行任务。在Mac OS X 10.6雪豹中首次推出,也可在IOS 4及以上版本使用。

GCD 中两个重要重要概念 —— 队列 & 任务

队列

队列是一种特殊的线性表,采用FIFO(先进先出)的原则,即新任务总是被插入到队列的末尾,而读取任务的时候总是从队列的头部开始读取。每读取一个任务,则从队列中释放一个任务。

队列的主要作用是用来存放任务。

GCD会自动将队列中的任务取出,放到对应的线程中执行。

**队列分类: **

  • 串行队列(Serial Dispatch Queue): 让任务一个接着一个地执行(一个任务执行完毕后,再执行下一个任务

  • 并发队列(Concurrent Dispatch Queue): 可以让多个任务并发(同时)执行(自动开启多个线程同时执行任务), 并发功能只有在异步(dispatch_async)函数下才有效
    > 由于队列同步执行不具有开启线程的能力,异步执行才可以开启线程。
    > 并发队列在异步执行才有效。

队列执行任务的方式:

  • 同步:在当前线程中执行,当前代码不执行完,就不能够执行下一条代码。会阻塞当前线程。

  • 异步:在另一条线程中执行(不用等待当前代码执行完,就能够执行下一条),不会阻塞当前线程。

常见队列:

为了方便 GCD 使用,苹果默认提供了主队列和全局队列。 我们不需要创建只需要获取。

  • 主队列 (串行)
let mainQueue = DispatchQueue.main
  • 全局队列 (并发)
let globalQueue = DispatchQueue.global()

全局队列默认是并发队列,在不进行第三方框架或者大型的商业应用开发,全局队列基本够用。

任务

需要执行操作, 任务是使用闭包( oc: block) 封装的代码块。

废话到此完毕!


1. 项目开发中 GCD 代码使用

print("DispatchQueue.main.sync: befor", Thread.current)
DispatchQueue.global().async {
       print("DispatchQueue.global().async: Time task", Thread.current, "\n --: 耗时操作在后台线程中执行!")
            
      DispatchQueue.main.async {
          print("DispatchQueue.main.async: update UI", Thread.current, "\n --: 耗时操作执行完毕后在主线程更新 UI 界面!")
      }
}
print("DispatchQueue.main.sync: after", Thread.current)


// 打印:
DispatchQueue.main.sync: befor <NSThread: 0x60800007abc0>{number = 1, name = main}
DispatchQueue.main.sync: after <NSThread: 0x60800007abc0>{number = 1, name = main}
DispatchQueue.global().async: Time task <NSThread: 0x6080002662c0>{number = 3, name = (null)} 
 --: 耗时操作在后台线程中执行!
DispatchQueue.main.async: update UI <NSThread: 0x60800007abc0>{number = 1, name = main} 
 --: 耗时操作执行完毕后在主线程更新 UI 界面!

/*
 after 执行的先后顺序是不确定的。是由 GCD 决定。
这里牵扯到一个概念: 线程间通讯! 说白的就是在线程间进行数据(信号)的传递。
*/

如果你只是单纯的找 GCD 在 swift 中怎么使用,看到这里你基本可以关掉这篇博客,开心的写代码去了。


2. GCD 使用 —— 精讲

先来了解 GCD 在 Swift 中的变化
GCD 框架头文件改变

import Dispatch.base         // 没有实质性内容
import Dispatch.block        // 没有实质性内容
import Dispatch.data         // 没有实质性内容
import Dispatch.group
import Dispatch.io
import Dispatch.object
import Dispatch.once        // 没有实质性内容
import Dispatch.queue
import Dispatch.semaphore
import Dispatch.source
import Dispatch.time
import Dispatch
import os_object

// 在 swift3.0 中新加的, OS_object 继承自 NSObject
// 在 GCD 中所有的对象都间接的继承自 NSObject。
import os_object
open class OS_object : NSObject {
}

Swift 中最大的变化其实就是更加的面相对象了,使用更加的方便简洁,摆脱了 OC 时代函数式的使用方式。

GCD 使用先来个个人小的总结:

口诀:同步不开异步开,串行开1条,并行开多条。

来,跟着哥一起念。( 我怕你们打我,你们还是别念了,我解释一下。)

同步不开异步开,串行开1条,并行开多条。
单纯这么简单的看是有误解的, 在我的评论中就可以看到。

具体的意思是:
队列中的任务同步执行,队列就不具有开启线程的能力, 队列中的任务异步执行,队列就具有开启线程的能力。
(同步和异步执行决定的是否有开启线程的能力)

如果队列具 **有开启线程的能力 (队列任务异步执行) ** 且队列是 串行队列 ,那么将会 开启 1 条线程
如果队列具 **有开启线程的能力 (队列任务异步执行) ** 且队列是 并发队列 ,那么将会 开启 多 条线程 。开启线程的条数由 GCD 决定。
** ( 串行和并发决定的是开几条线程 ) **

** 如果真正理解了上面这些,多 GCD 的使用和面试基本没什么障碍。 **

2.1 全局队列

全局队列是获取的,不是程序员创建的。
为了方便 GCD 的使用,apple 默认为我们提供的。
全局队列默认是并发队列,在不是进行第三方框架或者大型的商业应用开发,全局队列基本够用。

全局 ( 并发 ) 队列异步执行 :

并发队列异步(不阻塞当前线程)执行(队列就具有开启线程的能力), 队列会开启多条线程。

任务异步执行不会阻塞当前线程, 
   befor 在最前, 
   after 在任意位置,
   task 执行顺序不确定 —— 并发执行(index可以确认)。
   task 并发执行 —— 并发执行(number可以确认)。

异步开线程 number 可以确定开启了多条线程
   开的线程数由 GCD 决定。 可以看到线程的 number 有重复,是 GCD 对线程进行了复用。
func async() {
    
    print("DispatchQueue.global().async: befor", Thread.current)
    // 全局队列进行 10次异步
    for index in 0..<10 {

        DispatchQueue.global().async {
            print("DispatchQueue.global().async: task:(taskIndex:\(index)", Thread.current)
        }
    }
    print("DispatchQueue.global().async: after", Thread.current)
}

打印:
     DispatchQueue.global().async: befor <NSThread: 0x60800006a8c0>{number = 1, name = main}
     DispatchQueue.global().async: task:(taskIndex:1 <NSThread: 0x600000079780>{number = 3, name = (null)}
     DispatchQueue.global().async: task:(taskIndex:2 <NSThread: 0x6000000797c0>{number = 4, name = (null)}
     DispatchQueue.global().async: task:(taskIndex:0 <NSThread: 0x600000079880>{number = 5, name = (null)}
     DispatchQueue.global().async: task:(taskIndex:3 <NSThread: 0x608000074e00>{number = 6, name = (null)}
     DispatchQueue.global().async: task:(taskIndex:4 <NSThread: 0x600000079780>{number = 3, name = (null)}
     DispatchQueue.global().async: task:(taskIndex:5 <NSThread: 0x6000000797c0>{number = 4, name = (null)}
     DispatchQueue.global().async: after <NSThread: 0x60800006a8c0>{number = 1, name = main}
     DispatchQueue.global().async: task:(taskIndex:6 <NSThread: 0x600000079880>{number = 5, name = (null)}
     DispatchQueue.global().async: task:(taskIndex:7 <NSThread: 0x608000074e00>{number = 6, name = (null)}
     DispatchQueue.global().async: task:(taskIndex:8 <NSThread: 0x600000079780>{number = 3, name = (null)}
     DispatchQueue.global().async: task:(taskIndex:9 <NSThread: 0x6000000797c0>{number = 4, name = (null)}

全局 ( 并发 ) 队列同步执行 :

并发队列同步(阻塞当前线程)执行(队列就不具有开启线程的能力), 队列不会开启线程(代码都在主线程中执行)。

任务同步执行会阻塞当前线程, 
     befor 在最前, 
     after 在最后,
     task 执行顺序确定 —— 阻塞。
同步没有开启线程 number 可以确定没有开启多条线程。所有的代码都在 主线程中执行。
func sync() {
    print("DispatchQueue.global().sync: befor", Thread.current)
    for index in 0..<10 {
        DispatchQueue.global().sync {
            print("DispatchQueue.global().sync: task:(taskIndex:\(index))", Thread.current)
        }
    }
    print("DispatchQueue.global().sync: after", Thread.current)
}


打印: 
DispatchQueue.global().sync: befor <NSThread: 0x60800007fa80>{number = 1, name = main}
DispatchQueue.global().sync: task:(taskIndex:0) <NSThread: 0x60800007fa80>{number = 1, name = main}
DispatchQueue.global().sync: task:(taskIndex:1) <NSThread: 0x60800007fa80>{number = 1, name = main}
DispatchQueue.global().sync: task:(taskIndex:2) <NSThread: 0x60800007fa80>{number = 1, name = main}
DispatchQueue.global().sync: task:(taskIndex:3) <NSThread: 0x60800007fa80>{number = 1, name = main}
DispatchQueue.global().sync: task:(taskIndex:4) <NSThread: 0x60800007fa80>{number = 1, name = main}
DispatchQueue.global().sync: task:(taskIndex:5) <NSThread: 0x60800007fa80>{number = 1, name = main}
DispatchQueue.global().sync: task:(taskIndex:6) <NSThread: 0x60800007fa80>{number = 1, name = main}
DispatchQueue.global().sync: task:(taskIndex:7) <NSThread: 0x60800007fa80>{number = 1, name = main}
DispatchQueue.global().sync: task:(taskIndex:8) <NSThread: 0x60800007fa80>{number = 1, name = main}
DispatchQueue.global().sync: task:(taskIndex:9) <NSThread: 0x60800007fa80>{number = 1, name = main}
DispatchQueue.global().sync: after <NSThread: 0x60800007fa80>{number = 1, name = main}

2.2 主队列

主队列是获取的,不是程序员创建的,apple 默认为我们提供的。
(app 开发中,所有的 UI 更新操作都应该在主线程中进行)

主队列(串行)异步执行

主队列异步(不会阻塞当前线程)执行(队列就具有开启线程的能力), 队列会开启线程(开启的线程就是主线程)。

> 有朋友问我,异步会开启线程, 主队列异步就不会开启线程。 
> 我当时还信以为真。认为自己错误,说特殊情况特殊处理。 其实说白了就是学艺不精。
> 由于主队列是我们获取的,不是我们创建的,在某种意识中会认为主线程不是在主队列中创建的。(认为一开始就存在的。)


> 任务异步执行不会阻塞当前线程, 
 befor 在最前, 
 after 在第二,
 task 执行顺序确定 —— 串行执行(index可以确认)。

同步没有开启线程 number 可以确定没有开启多条线程。所有的代码都在 主线程中执行。

主队列异步的操作主要用在更新 UI 操作中。 具体参考 项目开发中 GCD 代码使用。

func async() {
        
        print("DispatchQueue.main.async: befor", Thread.current)
        for index in 0..<10 {
            DispatchQueue.main.async {
                print("DispatchQueue.main.async: task:(taskIndex:\(index)", Thread.current)
            }
        }
        print("DispatchQueue.main.async: after", Thread.current)
}

打印: 
DispatchQueue.main.async: befor <NSThread: 0x60800006ddc0>{number = 1, name = main}
DispatchQueue.main.async: after <NSThread: 0x60800006ddc0>{number = 1, name = main}
DispatchQueue.main.async: task:(taskIndex:0 <NSThread: 0x60800006ddc0>{number = 1, name = main}
DispatchQueue.main.async: task:(taskIndex:1 <NSThread: 0x60800006ddc0>{number = 1, name = main}
DispatchQueue.main.async: task:(taskIndex:2 <NSThread: 0x60800006ddc0>{number = 1, name = main}
DispatchQueue.main.async: task:(taskIndex:3 <NSThread: 0x60800006ddc0>{number = 1, name = main}
DispatchQueue.main.async: task:(taskIndex:4 <NSThread: 0x60800006ddc0>{number = 1, name = main}
DispatchQueue.main.async: task:(taskIndex:5 <NSThread: 0x60800006ddc0>{number = 1, name = main}
DispatchQueue.main.async: task:(taskIndex:6 <NSThread: 0x60800006ddc0>{number = 1, name = main}
DispatchQueue.main.async: task:(taskIndex:7 <NSThread: 0x60800006ddc0>{number = 1, name = main}
DispatchQueue.main.async: task:(taskIndex:8 <NSThread: 0x60800006ddc0>{number = 1, name = main}
DispatchQueue.main.async: task:(taskIndex:9 <NSThread: 0x60800006ddc0>{number = 1, name = main}

主队列(串行)同步执行

执行的效果就俩字 ** 死锁**

主线程同步,在 Swift 中,编译阶段就报错,在 oc 中是在运行的时候才能发现。体现的主要是界面的 “假死”。


Snip20170316_1.png

2.3 自定义队列

/*
label:   队列名称
qos: 服务质量
     // 后台优先级
     public static let background: DispatchQoS
    // 实用工具优先级别(耗时操作,可以使用这个)
    public static let utility: DispatchQoS
    // 默认优先级(一般不是给程序员实用的,用来重置队列用的)
    public static let `default`: DispatchQoS
    //  用户期望优先级(不要放太耗时的操作)
    public static let userInitiated: DispatchQoS
    // 用户交互(希望尽快完成,用户很希望得到结果。个人觉得这个和主线的的线程优先级是一样的)
    public static let userInteractive: DispatchQoS
    // 未指定
    public static let unspecified: DispatchQoS


attributes: 队列属性
        // 并发
        public static let concurrent: DispatchQueue.Attributes
        // 初始化不活跃
        public static let initiallyInactive: DispatchQueue.Attributes

autoreleaseFrequency: 自动释放频率
          public enum AutoreleaseFrequency {
              // 继承
              case inherit
              // 工作项
              case workItem
              // 从来没有,永远不
              case never
           }
  target: 目标队列

( 这些参数我也没搞明白)
*/
public convenience init(label: String, 
                          qos: DispatchQoS = default, 
                   attributes: DispatchQueue.Attributes = default, 
         autoreleaseFrequency: DispatchQueue.AutoreleaseFrequency = default,
                       target: DispatchQueue? = default)

在没有搞明白参数的时候,由于 swift 可以使用默认参数, 我们可以使用默认参数。

自定义(串行)队列异步执行

// 使用默认的构造函数创建了一个队列(并不知队列是串行还是并发)
// api 文档没有给够足够的信息。 后期的文档描述完整后可以直接查看文档。

func async() {
        
        print("DispatchQueue(label: \"laughing\").async: befor", Thread.current)
        let queue = DispatchQueue(label: "laughing")
        for index in 0..<10 {
            queue.async {
                print("DispatchQueue(label: \"laughing\").async: task:(taskIndex:\(index)", Thread.current)
            }
        }
        print("DispatchQueue(label: \"laughing\").async: after", Thread.current)
 }

      /*
         这么写你会有一种串行队列并发执行的错觉。
        for index in 0..<10 {
            DispatchQueue(label: "laughing").sync {
                print("DispatchQueue(label: \"laughing\").sync: task:(taskIndex:\(index))", Thread.current)
            }
        }
       */

打印:
DispatchQueue(label: "laughing").async: befor <NSThread: 0x608000067180>{number = 1, name = main}
DispatchQueue(label: "laughing").async: after <NSThread: 0x608000067180>{number = 1, name = main}
DispatchQueue(label: "laughing").async: task:(taskIndex:0 <NSThread: 0x608000074200>{number = 3, name = (null)}
DispatchQueue(label: "laughing").async: task:(taskIndex:1 <NSThread: 0x608000074200>{number = 3, name = (null)}
DispatchQueue(label: "laughing").async: task:(taskIndex:2 <NSThread: 0x608000074200>{number = 3, name = (null)}
DispatchQueue(label: "laughing").async: task:(taskIndex:3 <NSThread: 0x608000074200>{number = 3, name = (null)}
DispatchQueue(label: "laughing").async: task:(taskIndex:4 <NSThread: 0x608000074200>{number = 3, name = (null)}
DispatchQueue(label: "laughing").async: task:(taskIndex:5 <NSThread: 0x608000074200>{number = 3, name = (null)}
DispatchQueue(label: "laughing").async: task:(taskIndex:6 <NSThread: 0x608000074200>{number = 3, name = (null)}
DispatchQueue(label: "laughing").async: task:(taskIndex:7 <NSThread: 0x608000074200>{number = 3, name = (null)}
DispatchQueue(label: "laughing").async: task:(taskIndex:8 <NSThread: 0x608000074200>{number = 3, name = (null)}
DispatchQueue(label: "laughing").async: task:(taskIndex:9 <NSThread: 0x608000074200>{number = 3, name = (null)}

** 由于只异步执行只开了1 条线程, 可只。 默认创建的队列是 串行队列**

自定义(串行)队列同步执行
串行队列同步执行,没有开启线程。 代码在主线程中执行。

  func sync() {
        print("DispatchQueue(label: \"laughing\").sync: befor", Thread.current)
        
        let queue = DispatchQueue(label: "laughing")
        for index in 0..<10 {
            queue.sync {
                print("DispatchQueue(label: \"laughing\").sync: task:(taskIndex:\(index))", Thread.current)
            }
        }
        
        /*
         这么写你会有一种串行队列并发执行的错觉。
        for index in 0..<10 {
            DispatchQueue(label: "laughing").sync {
                print("DispatchQueue(label: \"laughing\").sync: task:(taskIndex:\(index))", Thread.current)
            }
        }
        */
        
        print("DispatchQueue(label: \"laughing\").sync: after", Thread.current)
    }

打印: 
DispatchQueue(label: "laughing").sync: befor <NSThread: 0x600000071d40>{number = 1, name = main}
DispatchQueue(label: "laughing").sync: task:(taskIndex:0) <NSThread: 0x600000071d40>{number = 1, name = main}
DispatchQueue(label: "laughing").sync: task:(taskIndex:1) <NSThread: 0x600000071d40>{number = 1, name = main}
DispatchQueue(label: "laughing").sync: task:(taskIndex:2) <NSThread: 0x600000071d40>{number = 1, name = main}
DispatchQueue(label: "laughing").sync: task:(taskIndex:3) <NSThread: 0x600000071d40>{number = 1, name = main}
DispatchQueue(label: "laughing").sync: task:(taskIndex:4) <NSThread: 0x600000071d40>{number = 1, name = main}
DispatchQueue(label: "laughing").sync: task:(taskIndex:5) <NSThread: 0x600000071d40>{number = 1, name = main}
DispatchQueue(label: "laughing").sync: task:(taskIndex:6) <NSThread: 0x600000071d40>{number = 1, name = main}
DispatchQueue(label: "laughing").sync: task:(taskIndex:7) <NSThread: 0x600000071d40>{number = 1, name = main}
DispatchQueue(label: "laughing").sync: task:(taskIndex:8) <NSThread: 0x600000071d40>{number = 1, name = main}
DispatchQueue(label: "laughing").sync: task:(taskIndex:9) <NSThread: 0x600000071d40>{number = 1, name = main}
DispatchQueue(label: "laughing").sync: after <NSThread: 0x600000071d40>{number = 1, name = main}

自定义(并发)队列异步执行
(参考全局队列)

func async1() {
    
    print("DispatchQueue(label: \"laughing1\").async: befor", Thread.current)
    let queue = DispatchQueue(label: "laughing1",  attributes: DispatchQueue.Attributes.concurrent)
    for index in 0..<10 {
        queue.async {
            print("DispatchQueue(label: \"laughing1\").async: task:(taskIndex:\(index)", Thread.current)
        }
    }
    print("DispatchQueue(label: \"laughing1\").async: after", Thread.current)
}

打印
DispatchQueue(label: "laughing1").async: befor <NSThread: 0x600000261d80>{number = 1, name = main}
DispatchQueue(label: "laughing1").async: after <NSThread: 0x600000261d80>{number = 1, name = main}
DispatchQueue(label: "laughing1").async: task:(taskIndex:1 <NSThread: 0x60800026d380>{number = 3, name = (null)}
DispatchQueue(label: "laughing1").async: task:(taskIndex:3 <NSThread: 0x60800026d380>{number = 3, name = (null)}
DispatchQueue(label: "laughing1").async: task:(taskIndex:4 <NSThread: 0x60800026d380>{number = 3, name = (null)}
DispatchQueue(label: "laughing1").async: task:(taskIndex:2 <NSThread: 0x60800026d9c0>{number = 4, name = (null)}
DispatchQueue(label: "laughing1").async: task:(taskIndex:5 <NSThread: 0x60800026d380>{number = 3, name = (null)}
DispatchQueue(label: "laughing1").async: task:(taskIndex:7 <NSThread: 0x60800026d9c0>{number = 4, name = (null)}
DispatchQueue(label: "laughing1").async: task:(taskIndex:6 <NSThread: 0x60800026da00>{number = 5, name = (null)}
DispatchQueue(label: "laughing1").async: task:(taskIndex:0 <NSThread: 0x60800026db40>{number = 6, name = (null)}
DispatchQueue(label: "laughing1").async: task:(taskIndex:8 <NSThread: 0x60800026d380>{number = 3, name = (null)}
DispatchQueue(label: "laughing1").async: task:(taskIndex:9 <NSThread: 0x60800026d9c0>{number = 4, name = (null)}

自定义(并发)队列同步执行

func sync1() {
    print("DispatchQueue(label: \"laughing1\").sync: befor", Thread.current)
    
    
    let queue = DispatchQueue(label: "laughing1",  attributes: DispatchQueue.Attributes.concurrent)
    for index in 0..<10 {
        queue.sync {
            print("DispatchQueue(label: \"laughing1\").sync: task:(taskIndex:\(index))", Thread.current)
        }
    }
    
    /*
     这么写你会有一种串行队列并发执行的错觉。
     for index in 0..<10 {
     DispatchQueue(label: "laughing").sync {
     print("DispatchQueue(label: \"laughing\").sync: task:(taskIndex:\(index))", Thread.current)
     }
     }
     */
    
    print("DispatchQueue(label: \"laughing1\").sync: after", Thread.current)
}


打印
DispatchQueue(label: "laughing1").sync: befor <NSThread: 0x608000061cc0>{number = 1, name = main}
DispatchQueue(label: "laughing1").sync: task:(taskIndex:0) <NSThread: 0x608000061cc0>{number = 1, name = main}
DispatchQueue(label: "laughing1").sync: task:(taskIndex:1) <NSThread: 0x608000061cc0>{number = 1, name = main}
DispatchQueue(label: "laughing1").sync: task:(taskIndex:2) <NSThread: 0x608000061cc0>{number = 1, name = main}
DispatchQueue(label: "laughing1").sync: task:(taskIndex:3) <NSThread: 0x608000061cc0>{number = 1, name = main}
DispatchQueue(label: "laughing1").sync: task:(taskIndex:4) <NSThread: 0x608000061cc0>{number = 1, name = main}
DispatchQueue(label: "laughing1").sync: task:(taskIndex:5) <NSThread: 0x608000061cc0>{number = 1, name = main}
DispatchQueue(label: "laughing1").sync: task:(taskIndex:6) <NSThread: 0x608000061cc0>{number = 1, name = main}
DispatchQueue(label: "laughing1").sync: task:(taskIndex:7) <NSThread: 0x608000061cc0>{number = 1, name = main}
DispatchQueue(label: "laughing1").sync: task:(taskIndex:8) <NSThread: 0x608000061cc0>{number = 1, name = main}
DispatchQueue(label: "laughing1").sync: task:(taskIndex:9) <NSThread: 0x608000061cc0>{number = 1, name = main}
DispatchQueue(label: "laughing1").sync: after <NSThread: 0x608000061cc0>{number = 1, name = main}

相关文章

  • 3、GCD-swift

    GCD 一直以来是基于 c 语言的。apple 为了使 GCD 使用更加的 swift 化。 对 GCD 进行了...

  • GCD-Swift 3 常见用法

    Swift 是完美支持GCD的,由于Swift的发展写法也一直在变动,下面列举一些常见的用法。 全局队列异步执行 ...

  • GCD-Swift 3 高级用法

    当今App中多线程是必不可少的因素,而GCD起着举足轻重的作用。下面我们来看看swift 3.0中的GCD,能给我...

  • 为什么要用GCD-Swift

    为什么要用GCD-Swift 当今世界,多核已然普及。但是APP却不见得很好的跟上了这个趋势。APP 想要利用好多...

  • 恶意文件夹

    【%你的iapp在这里哦/恭喜你找到了/3/3/3/3/3/3/3/3/3/3/3/3/3/3/3/3/3/3/3...

  • 3+3+3

    九年了,不曾去过,马路那边的刘家村。唱戏,小路~抓蝌蚪,洗衣服,捞水草,漩涡~种满菜的田地,养着奶牛的茅草屋,充满...

  • 3/3

    郭一博 刘佐千 李文浩 王天聪 柳絮 刘全利 李明东

  • 3/3

  • if(a==3) or if(3==a)

    记得刚写程序那会儿,遇到 if else 的条件判断逻辑,基本都会这样写:if(a==3) 为什么呢? 因为自然...

  • 3/3

    原先我是为了他留长头发,现在他的女朋友剪了短发,他说随她去,都好。 原先她卑微付出真心为他,现在她是个被宠溺的幸福...

网友评论

  • 潶佰:同步不开异步开亮了:flushed:
  • XIAODAO:你好,请问“在 GCD 中所有的对象都间接的继承自 NSObject”这个从哪里可以看出来?
    Laughingg:@XIAODAO 其实你没必要关注这些无关紧要的东西。
    XIAODAO:@Laughingg 我用的是Xcode8.3.3 ,Swift3,头文件里没有看到类似“在 GCD 中所有的对象都间接的继承自 NSObject”的意思,只是说为了能够调用runtime,OS_object classes can be marked as OS_OBJECT_OBJC_RUNTIME_VISIBLE
    Laughingg:@XIAODAO 你可以翻一下头文件。 我这个是swift3.0 的。 swift4.0 有没有改我就不知道了
  • SuDream:写的不错,写作的风格可以幽默,看着不乏味,期待更多知识贴
  • 壹点微尘:学习了
  • 琴月阳:异步不一定会新开辟线程的吧,主队列的异步操作就不会
    Laughingg:主队列的异步操作 开启的其实就是 主线程
    Laughingg:我被你蒙了。


    同步不具有开启线程的能力,异步有开启线程的能力, 如果队列具有开启线程的能力,串行队列(异步执行)会开启1 条新线程, 并发队列(异步执行)会开启多条线程(具体开几条线程是由gcd 决定)。


    特殊情况:
    主队列(串行队列),同步执行, 死锁。
    主队列, 异步执行(具有开启线程的能力),会开一1 条线程(主线程)
    (由于主队列的特殊性, 主队列异步开启的线程就是主线程)

    全局队列(并发队列), 同步执行,不会开启线程。( task 会在主线程中执行)
    全局队列 ,异步执行(具有开启线程的能力), 会开启新线程。线程的条数是由 gcd 决定。


    自定义队列
    自定义串行队列,同步执行(不具有开启线程的能力),不会开启新的线程(主线程中执行)。
    自定义串行队列,异步执行(具有开启线程的能力),会开启1条新的线程。

    自定义并发队列和全局队列类似
    Laughingg:你说的没错啊!特殊情况,特殊对待。
  • tom555cat:serialQueue应该怎么会翻译成同步队列呢?是谁和谁同步呢?
  • 顶级蜗牛:最后的一个实例,图片的格式错了
    顶级蜗牛:@Laughingg swift3.0改了API NSThread.currentThread() -> NSThread.current
    Laughingg:@顶级蜗牛 你也太仔细了吧。 我是复制粘贴的。可能是手误的原因。
  • 新地球说着一口陌生腔调:看到线程复用 才复用一个呀!
  • 王梓舟:这是一篇很赞的文章
  • OSong:谢谢啦。线程的写法Swift2.3。Swift3.0变化好大。
  • 77ba8e0a2ddc:为啥我下载图片那野指针 呢?
    Laughingg:@erU 我是没看懂。 代码是 swift3.0 beta 版本的时候写的。可能存在点小问题。有空我再整理一下。
    erU:@努力的女孩 你这表达的。。
  • erU:博主这又问题吧!
    默认队列和全局队列一样。也是串行队列。
    全局队列是并发队列!
    求解答。新手
    Laughingg:手误
    77ba8e0a2ddc:@erU 我也试了:默认队列和全局队列不一样,估计手误吧
  • Laughingg:主线程串行不就卡死了啊

本文标题:3、GCD-swift

本文链接:https://www.haomeiwen.com/subject/dozwdttx.html