me
me copied to clipboard
学习 MacOS 开发 (Part 13: Dispatch)
main.swift
import SwiftUI
print("#1")
DispatchQueue.main.async {
print("#2")
}
print("#3")
print(Thread.current)
RunLoop.main.run()
Output:
# 1
# 3
#3
<_NSMainThread: 0x600001be8440>{number = 1, name = main}
# 2
这个sample中主要涉及三个概念:
- DispatchQueue
- RunLoop
- Thread
DispatchQueue
GCD介绍(一):基本概念和Dispatch Queue-51CTO.COM
- DispatchQueue代表表示单一线程或一个线程池, 将block委托给一个指定的queue来执行,苹果重新构架了一个任务执行的模型
- 三种类型:
- main queue: 串线主线程,一个程序中有且只有一个,在SwiftUI中即UI线程
- global queue: 并行线程池,整个进程共享
- worker queue: 用户自己创建,串行队列
继续看视频: Concurrent Programming With GCD in Swift 3 - WWDC16 - Videos - Apple Developer
- 重新建立抽象: Dispatch Queues 和 Run Loops
- Dispatch Queues是一个队列,即任务队列,即swift closure队列
- Dispatch Queues和Thread既可以独立也可以一起出现,你可以请GCD帮你创建线程,也可以你来创建后给DQ去使用
- 可以提交同步和异步两种类型的工作任务

Conccurent
serial dispatch queue
let queue = DispatchQueue(label: "cn.nonocast.queue")
queue.async {
Thread.sleep(forTimeInterval: 3)
print("3 sec task done.")
}
queue.async {
Thread.sleep(forTimeInterval: 1)
print("1 sec task done.")
}
print(Thread.current)
RunLoop.main.run()
输出:
<_NSMainThread: 0x600002e64600>{number = 1, name = main}
3 sec task done.
1 sec task done.
concurrent dispatch queue
let queue = DispatchQueue(label: "cn.nonocast.queue", attributes: .concurrent)
输出:
<_NSMainThread: 0x600000dc85c0>{number = 1, name = main}
1 sec task done.
3 sec task done.
总结
- GCD是苹果对多线程,同步异步执行的抽象框架,隐藏了pthread,使用前你需要充分理解这个模型
- queue分为单线程和线程池两种模式,即serial和concurrent
- 程序启动自带一个main runloop和main queue,这个main queue主要为UI服务,且是serial
- 同时一个程序会产生一个lazy的global queue,这个queue是concurrent
- 当你需要处理一个后台事务时,即不在main queue时,你有两个选择: global queue或是自建work queue, 这个选择取决于任务是serial还是concurrent以及任务的QoS
- 比如device capture需要一个queue时,由于需要serial处理,按顺序排列,所以这是main queue和global quque都不合适,应该自建worker serial queue最为合理
- 当任务过于复杂(比如图像分析或性能不够)导致任务处理时间大于图像pump时间导致的堆积,则应该采取降低pump频率的策略,即降低桢率或去掉复杂的任务
以上。