Swift系列三十一 - 多线程
Posted 1024星球
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Swift系列三十一 - 多线程相关的知识,希望对你有一定的参考价值。
多线程在Swift中也是首先使用GCD。
一、异步
1.1. GCD开启异步线程
示例代码:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
print("主线程", Thread.current)
DispatchQueue.global().async {
print("子线程", Thread.current)
DispatchQueue.main.async {
print("回到主线程", Thread.current)
}
}
}
}
/*
输出:
主线程 <NSThread: 0x600000bdc6c0>{number = 1, name = main}
子线程 <NSThread: 0x600000bb4c80>{number = 6, name = (null)}
回到主线程 <NSThread: 0x600000bdc6c0>{number = 1, name = main}
*/
提示:之前OC中很多类都是
NS
前缀,但是Swift中和OC对等的类名大部分把NS
去掉了。
1.2. GCD任务-DispatchWorkItem
DispatchWorkItem
是定义任务的,任务完成后可以通过notify
通知其他线程(一般是主线程)做其他任务。
示例代码:
// 定义任务
public typealias Task = () -> Void
public struct Async {
// 异步线程1:传入子线程任务
public static func async (_ task: @escaping Task) {
_async(task)
}
// 异步线程2:分别传入子线程和主线程的任务
public static func async(_ task: @escaping Task, _ mainTask: @escaping Task) {
_async(task, mainTask)
}
public static func _async(_ task: @escaping Task, _ mainTask: Task? = nil) {
let item = DispatchWorkItem(block: task)
// 子线程执行任务
DispatchQueue.global().async(execute: item)
if let main = mainTask {
// 子线程执行完毕后通知主线程执行任务
item.notify(queue: DispatchQueue.main, execute: main)
}
}
}
二、延迟
2.1 普通延迟
在ios中使用延迟一般使用dispatch_after
,但是在Swift中没有这个API,使用的是DispatchQueue.*.asyncAfter
。
示例代码:
@discardableResult
public static func delay(_ seconds: Double, _ block: @escaping Task) -> DispatchWorkItem {
let item = DispatchWorkItem(block: block)
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + seconds, execute: item)
return item
}
2.2. 异步延迟
示例代码(定义函数):
@discardableResult
public static func asyncDelay(_ seconds: Double, _ task: @escaping Task) -> DispatchWorkItem {
return _asyncDelay(seconds, task)
}
@discardableResult
public static func asyncDelay(_ seconds: Double, _ task: @escaping Task, _ mainTask: @escaping Task) -> DispatchWorkItem {
return _asyncDelay(seconds, task, mainTask)
}
private static func _asyncDelay(_ seconds: Double, _ task: @escaping Task, _ mainTask: Task? = nil) -> DispatchWorkItem {
let item = DispatchWorkItem(block: task)
DispatchQueue.global().asyncAfter(deadline: DispatchTime.now() + seconds, execute: item)
if let main = mainTask {
item.notify(queue: DispatchQueue.main, execute: main)
}
return item
}
示例代码(使用):
class ViewController: UIViewController {
private var item: DispatchWorkItem?
override func viewDidLoad() {
super.viewDidLoad()
item = Async.asyncDelay(3) {
};
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
item?.cancel()
}
}
为什么定义延迟异步时函数要返回DispatchWorkItem
?是因为有可能需要对任务做取消或其他操作。
三、once
dispatch_once
在Swift中已被废弃,取而代之的是静态属性(底层还是调用了dispatch_once
)。
示例代码:
class ViewController: UIViewController {
static var onceTask: Void = {
print("onceTask")
}()
override func viewDidLoad() {
super.viewDidLoad()
let _ = Self.onceTask
let _ = Self.onceTask
let _ = Self.onceTask
}
}
// 输出:print("onceTask")
四、加锁
当很多资源同时访问同一块数据的时候,可能会发生抢夺资源的情况,这时候需要一个加锁机制,当上次任务还未结束时,等待到任务完成才能继续下一次任务。
示例代码:
public struct Cache {
private static var data = [String: Any]()
private static var lock = DispatchSemaphore(value: 1)
public static func set(_ key: String, _ value: Any) {
lock.wait()
defer {
lock.signal()
}
data[key] = value
}
}
lock.wait()
是加锁,lock.signal()
是取消锁(解锁)。加锁的API还有很多:NSLock、NSRecursiveLock
等等,使用起来都很简单(只需要注意死锁问题即可)。
以上是关于Swift系列三十一 - 多线程的主要内容,如果未能解决你的问题,请参考以下文章
Qt系列文章之三十一 (基于QThread互斥量的线程同步线程)
MATLAB实战系列(三十一)-基于MATLAB的异步电机调速系统仿真
第三十一节:扫盲并发和并行同步和异步进程和线程阻塞和非阻塞响应和吞吐等