最后更新:2019年3月31日。
如果您喜欢这个项目,请给它点个 star ⭐ 这将表示您对创建者的赞赏,并将帮助他人发现这个存储库。
✍️ 关于
🏗 安装
CocoaPods
concurrency-kit
通过CocoaPods
提供。
pod 'concurrency-kit', '~> 1.1.1'
手动操作
您始终可以使用复制粘贴源代码的方法。
🔥 功能
- 原子操作 - 以多种形式实现(通用型、整型、布尔型)的同步原语。
快速
. 在内部使用了一个互斥锁(pthread_mutex_lock
),比OSSpinLock
更高效,比NSLock
更快。可抛出异常
。您可以安全地抛出Errors
,并能够委托处理。
- 锁 - 包含了多个锁,例如
UnfairLock
- 一个会让尝试获取锁的线程在一个循环(“自旋”)中等待,并反复检查锁是否可用。ReadWriteLock
-读/写锁允许对仅读操作进行并发访问,而写入操作则需要独占访问。Mutex
- 允许只在一个特定的代码区域中有一个线程是活动的。
- DispatchQueue+Extensions - 扩展了
DispatchQueue
,其中asyncAfter
和once
方法增加了便利性。 - 任务 - 是一个执行特定工作并通常与其他任务并行的作业单元。
- 任务可以是
分组
的 —— 意味着您可以将任务组合起来,类似于Futures & Promises
,并按顺序执行它们。 - 任务可以是
顺序执行
的 —— 意味着您可以将不同的groups
组合起来并并发执行它们。无需重复使用DispatchGroup
(enter
/leave
)。
- 任务可以是
- 具有状态的运算 - 是一个自定义的
Operation
类,通过使用Atomics
和Enum
类型支持现代的Swifty
状态管理。 - 彻底测试过。
📚 示例
任务
为了创建一个 Task
,您只需要使用 Task
结构和后置闭包语法。
let uploadingTask = Task { controller in
uploader(photos) { result in
switch result {
case .success:
controller.finish()
case .failure(let error):
controller.fail(with error)
}
}
}
uploadingTask.perform { outcome in
handle(outcome)
}
您可以将任务分组,这样并发操作将会按顺序执行,一个接一个。然后,您可以在链中添加一个完成闭包来处理结果
let filesToUpload = [file, photo, video, xml]
let group = Task.group(fileToUpload)
group.perform { outcome in
handle(outcome)
}
或者您可以将一组任务并发执行。它们将被异步执行,如果是可能的,它们将平行或并发执行,这取决于 GCD
。
let filesToUpload = [file, photo, video, xml]
let group = Task.sequence(filesToUpload)
group.perform { outcome in
handle(outcome)
}
具有状态的运算
具有更多“Swifty”状态管理系统的运算,其中状态是一个枚举类型,具有多种可能的情况。为了演示典型用法,让我们定义一个新的自定义网络请求运算
class NetworkStatefulOperation: StatefullOperation {
// MARK: - Properties
private let callback: (StatefullOperation?) -> Void
private let service: NetworkService
private let dataHandler: Parsable
// MARK: - Initializers
init(_ service: NetworkService, _ dataHandler: Parser, callback: @escaping (StatefullOperation?) -> Void) {
self.service = service
self.dataHandler = dataHandler
self.callback = callback
}
// MARK: - Overrides
override func executableSection() {
service.dataTask { [weak self] result in
self?.dataHandler.parse(result)
self?.finishIfNotCancelled()
self?.callback(self)
}
}
}
然后,NetworkStatefulOperation
类的使用方法相当简单
// 1. Create an instance of `NetworkStatefulOperation` class:
let networkiOperation = NetworkStatefulOperation(service, parser) {
// 3. As soon as the operation is finished, this closure will be executed with the operation state that can futher be handled to properly update the UI:
updateUI(with: $0.state)
}
// 2. Then call the `start` method:
networkOperation.start()
原子操作
保证了在多个异步调度队列中安全修改一个属性。只需将一个属性包裹在 Atomic
类型中即可。
let atomic = Atomic(0)
DispatchQueue.global().async {
atomic.modify { $0 + 1 }
}
DispatchQueue.global().async {
atomic.modify { $0 + 1 }
}
您还可以使用性能更加友好的AtomicInt
和AtomicBool
类,因此涉及不到动态调度(尽管Swift编译器足够智能,会应用称为编译时泛型专用化
的编译器优化[查看详情])。
锁
读写锁
一种同步原语,用于解决读者-写者问题之一
let rwLock = ReadWriteLock()
rwLock.writeLock()
sharedValue += 1
rwLock.unlock()
或者您还可以限制读取访问,这样其他线程将无法在释放锁之前读取属性被修改后的值
let rwLock = ReadWriteLock()
rwLock.readLock()
sharedValue += 1
rwLock.unlock()
不公平锁
导致试图获取锁的线程简单地在一个循环中等待(“自旋”),同时反复检查锁是否可用
let unfairLock = UnfairLock()
unfairLock.lock()
sharedValue += 1
unfairLock.unlock()
互斥锁
用于保护共享资源。互斥锁归获取它的任务所有。在给定的代码区域中,只有一个线程是活动的。
let mutex = Mutex()
mutex.withCriticalScope {
return sharedValue += 1
}
派发队列
有一个便捷的方法,无需传递.now() + time
即可进行异步调用
DispatchQueue.main.asyncAfter(seconds: 2.5) {
expectation.fulfill()
}
此外,还返回了:DispatchQueue.once
:
// The following concurrentQueue is called multiple times, though the caughtValue will be set to value only once.
concurrentQueue.async {
DispatchQueue.once(token: "caught") {
caughtValue = value
}
}
👨💻 作者
🔖 许可证
该项目可在MIT许可证下使用。