在Swift中编写命令行工具(CLT)时,我想处理大量数据.我已经确定我的代码是CPU限制的,性能可以从使用多个内核中受益.因此,我想并行化部分代码.说我想实现以下伪代码:
Fetch items from database
Divide items in X chunks
Process chunks in parallel
Wait for chunks to finish
Do some other processing (single-thread)
Run Code Online (Sandbox Code Playgroud)
现在我一直在使用GCD,一个天真的方法看起来像这样:
let group = dispatch_group_create()
let queue = dispatch_queue_create("", DISPATCH_QUEUE_CONCURRENT)
for chunk in chunks {
dispatch_group_async(group, queue) {
worker(chunk)
}
}
dispatch_group_wait(group, DISPATCH_TIME_FOREVER)
Run Code Online (Sandbox Code Playgroud)
但是GCD需要一个运行循环,因此代码将在组永远不会执行时挂起.runloop可以启动dispatch_main()
,但它永远不会退出.也可以运行NSRunLoop
几秒钟,但这不是一个坚实的解决方案.无论GCD如何,使用Swift如何实现?
Bou*_*uke 10
我错误地将锁定线程解释为挂起程序.没有运行循环,工作将执行得很好.问题中的代码运行正常,并阻止主线程直到整个组完成.
所以说chunks
包含4项工作量,下面的代码会旋转4个并发工作者,然后等待所有工作者完成:
let group = DispatchGroup()
let queue = DispatchQueue(label: "", attributes: .concurrent)
for chunk in chunk {
queue.async(group: group, execute: DispatchWorkItem() {
do_work(chunk)
})
}
_ = group.wait(timeout: .distantFuture)
Run Code Online (Sandbox Code Playgroud)
就像使用Objective-C CLI一样,您可以使用自己的运行循环NSRunLoop
.
这是一个可能的实现,从这个要点建模:
class MainProcess {
var shouldExit = false
func start () {
// do your stuff here
// set shouldExit to true when you're done
}
}
println("Hello, World!")
var runLoop : NSRunLoop
var process : MainProcess
autoreleasepool {
runLoop = NSRunLoop.currentRunLoop()
process = MainProcess()
process.start()
while (!process.shouldExit && (runLoop.runMode(NSDefaultRunLoopMode, beforeDate: NSDate(timeIntervalSinceNow: 2)))) {
// do nothing
}
}
Run Code Online (Sandbox Code Playgroud)
正如马丁指出的那样,你可以用
NSDate.distantFuture() as NSDate
而不是NSDate(timeIntervalSinceNow: 2)
.(转换是必要的,因为distantFuture()
方法签名表明它返回AnyObject
.)
如果您需要访问CLI参数,请参阅此答案.您也可以使用返回退出代码exit()
.
Aaron Brager 解决方案的 Swift 3 最小实现,它简单地组合autoreleasepool
和RunLoop.current.run(...)
直到打破循环:
var shouldExit = false
doSomethingAsync() { _ in
defer {
shouldExit = true
}
}
autoreleasepool {
var runLoop = RunLoop.current
while (!shouldExit && (runLoop.run(mode: .defaultRunLoopMode, before: Date.distantFuture))) {}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2814 次 |
最近记录: |