swift 多线程下
Swift
多线程编程方案:
Thread
Cocoa Operation
(Operation
和OperationQueue
)Grand Central Dispath
(GCD
)
1. Thread
在三种多线程技术中是最轻量级的, 但需要自己管理线程的生命周期和线程同步. 线程同步对数据的加锁会有一定的系统开销.
detachNewThread(_ block: @escaping () -> Void)
detachNewThreadSelector(_ selector: Selector, to Target target: Any, with argument: Any?)
e.g.
for i in 0...10 {
Thread.detachNewThread {
print("\(i) \(Thread.current)")
}
}
输出结果:
8 <NSThread: 0x6000000f8e40>{number = 12, name = (null)}
10 <NSThread: 0x6000000f0240>{number = 17, name = (null)}
7 <NSThread: 0x6000000cc0c0>{number = 10, name = (null)}
1 <NSThread: 0x6000000c0180>{number = 14, name = (null)}
6 <NSThread: 0x6000000efe80>{number = 9, name = (null)}
4 <NSThread: 0x6000000efdc0>{number = 11, name = (null)}
5 <NSThread: 0x6000000c8580>{number = 15, name = (null)}
9 <NSThread: 0x6000000cc080>{number = 8, name = (null)}
0 <NSThread: 0x6000000fd300>{number = 7, name = (null)}
2 <NSThread: 0x6000000cc5c0>{number = 13, name = (null)}
3 <NSThread: 0x6000000f0780>{number = 16, name = (null)}
e.g.
class ObjectForThread {
func threadTest() -> Void {
let thread = Thread(target: self, selector: #selector(threadWorker), object: nil)
thread.start()
print("threadTest")
}
@objc func threadWorker() -> Void {
print("threadWorker Run")
}
}
let obj = ObjectForThread()
obj.threadTest()
输出结果:
threadTest
threadWorker Run
2. Operation
和OperationQueue
Operation
- 面向对象 (
Operation
和BlockOperation
) Operation
+OperationQueue
- 取消、依赖、任务优先级、复杂逻辑、保存业务状态、子类化
Operation
的四种状态 :
isReady
isExecuting
isFinished
isCancelled
OperationQueue
OperationQueue
队列里可以加入很多个Operation
, 可以把OperationQueue
看做一个线程池, 可以往线程池中添加操作(Operation
)到队列中- 底层使用
GCD
maxConcurrentOperationCount
可以设置最大并发数defaultMaxConcurrentOperationCount
根据当前系统条件动态确定的最大并发数- 可以取消所有
Operation
, 但是当前正在执行的不会取消 - 所有
Operation
执行完毕后退出销毁
e.g.
BlockOperation
class ObjectForThread {
func threadTest() -> Void {
let operation = BlockOperation { [weak self] in
self?.threadWorker()
}
let queue = OperationQueue()
queue.addOperation(operation)
print("threadTest")
}
}
let obj = ObjectForThread()
obj.threadTest()
e.g. 自定义的
Operation
class ObjectForThread {
func threadTest() -> Void {
let operation = MyOperation()
operation.completionBlock = {() -> Void in
print("完成回调")
}
let queue = OperationQueue()
queue.addOperation(operation)
print("threadTest")
}
}
class MyOperation: Operation {
override func main() {
sleep(1)
print("MyOperation")
}
}
let obj = ObjectForThread()
obj.threadTest()
3. GCD
GCD
特点
- 任务+队列
- 易用
- 效率
- 性能
GCD
- 队列
- 主队列: 任务在主线程执行
- 并行队列: 任务会以先进先出的顺序入列和出列, 但是因为多个任务可以并行执行, 所以完成顺序是不一定的.
- 串行队列: 任务会以先进先出的顺序入列和出列, 但是同一时刻只会执行一个任务
GCD
- 队列API
Dispatch.main
Dispatch.global
DispatchQueue(label:,qos:,attributes:,autoreleaseFrequency:,target:)
queue.label
setTarget(queue:DispatchQueue)
- 最终的目标队列都是主队列和全局队列
- 如果把一个并行队列的目标队列都设置为同一个串行队列, 那么这多个队列连同目标队列里的任务都将串行执行
- 如果设置目标队列成环了, 结果是不可预期的
- 如果在一个队列正在执行任务的时候更换目标队列, 结果也是不可预期的
e.g.
let queue = DispatchQueue(label: "myQueue", qos: .default, attributes: .concurrent, autoreleaseFrequency: .inherit, target: nil)
queue.async {
sleep(3)
print("queue")
}
print("end")
e.g.
let queue = DispatchQueue(label: "myQueue", qos: .default, attributes: .concurrent, autoreleaseFrequency: .inherit, target: nil)
queue.asyncAfter(deadline: DispatchTime.now() + 10) {
print("in asyncAfter")
}
print("end")
DispatchTime
系统时钟DispatchWallTime
生活时间
GCD
高级特性- DispatchGroup
e.g. 阻塞当前线程
let group = DispatchGroup()
let queue = DispatchQueue(label: "test.queue")
group.enter()
queue.async {
sleep(3)
print("操作 1")
group.leave()
}
group.enter()
queue.async {
sleep(3)
print("操作 2")
group.leave()
}
print("操作1 操作2 安排完成")
group.wait()
print("操作1 操作2 全部执行完毕")
e.g. 非阻塞方式:
let group = DispatchGroup()
let queue = DispatchQueue(label: "test.queue")
group.enter()
queue.async {
sleep(3)
print("操作 1")
group.leave()
}
group.enter()
queue.async {
sleep(3)
print("操作 2")
group.leave()
}
print("操作1 操作2 安排完成")
group.notify(queue: queue) {
print("操作1 操作2 全部执行完毕")
}
print("非阻塞")
GCD
高级特性- DispatchSource
- 简单来说,
dispatch source
是一个监听某些类型事件的对象. 当这些事件方法时, 它自动将一个task
放入一个dispatch queue
的执行历程中.
e.g.
DispatchSource
-Timer
var seconds = 10
let timer: DispatchSourceTimer = DispatchSource.makeTimerSource(flags: .strict, queue: .global())
timer.schedule(deadline: .now(), repeating: 1.0)
timer.setEventHandler {
seconds -= 1
if seconds < 0 {
timer.cancel()
}
else {
print(seconds)
}
}
timer.resume()
链接:https://www.jianshu.com/p/b52728779891