根据 swift 中的某些条件执行同时操作
perform simultaneous operations based on the some conditions in swift
我必须根据某些条件执行一组操作,例如从数据库中获取数据,每次查询大约需要 10 秒(ConnectedDevices.getAllDetails() 需要 10 秒才能执行,return 结果)。
这可能类似于以下问题
但就我而言,我需要按以下代码所示批量执行操作:
var isConditionTrue = false
var numProcessed = 0
let dbQueue = dispatch_queue_create("dbQueue", DISPATCH_QUEUE_SERIAL)
// case 1
for i in 1...10 {
dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_UTILITY.value), 0)) {
let eachDBValue = ConnectedDevices.getAllDetails(i)
dispatch_async(dbQueue) {
if !eachDBValue {
numProcessed++
}
}
}
}
// case 2
for i in 11...20 {
dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_UTILITY.value), 0)) {
let eachDBValue = ConnectedDevices.getAllDetails(i)
dispatch_async(dbQueue) {
if !eachDBValue {
numProcessed++
}
}
}
}
// case 3
for i in 21...30 {
dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_UTILITY.value), 0)) {
let eachDBValue = ConnectedDevices.getAllDetails(i)
dispatch_async(dbQueue) {
if !ieachDBValue {
numProcessed++
}
}
}
}
// case 4
for i in 31...40 {
dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_UTILITY.value), 0)) {
let eachDBValue = ConnectedDevices.getAllDetails(i)
dispatch_async(dbQueue) {
if !eachDBValue {
numProcessed++
}
}
}
}
因此,如果在案例 1 中,如果 1 到 10 的结果为假,那么它应该转到案例 2。如果任何实例的结果为真.. 它不应该执行任何案例 2、3、4。
与情况 2 类似,如果 1 到 10 的结果为假,则应转到情况 3,否则应停止。
这一切我需要根据条件做。
这是我的解决方案
假的 ConnectedDevices class
这是我为了测试你的场景而创建的假 class。如您所见,方法 getAllDetails
确实模拟了您的数据库访问。
它等待 10 秒,然后仅当输入参数为 40
时 returns true
。这样我们就可以在最坏的情况下测试这段代码,因为所有的调用都需要完成。
class ConnectedDevices {
class func getAllDetails(i:Int) -> Bool {
sleep(10)
return i == 40
}
}
装载机class
这是将与 Grand Central Dispatch
交互的 class。
class Loader {
private var numProcessed = 0
private let dbQueue = dispatch_queue_create("dbQueue", DISPATCH_QUEUE_SERIAL)
private let utilityQueue = dispatch_get_global_queue(QOS_CLASS_UTILITY, 0)
func search(completion:(result:Int?)->()) {
dispatch_async(utilityQueue) {
for group in [1, 11, 21, 31] {
if let indexFound = self.search10(group) {
completion(result: indexFound)
return
}
}
completion(result: nil)
}
}
private func search10(startingIndex:Int) -> Int? {
var indexFound : Int?
dispatch_apply(10, utilityQueue) { (delta) -> () in
let found = ConnectedDevices.getAllDetails(startingIndex + delta)
dispatch_sync(self.dbQueue) {
self.numProcessed++ // this is increased anyway
if found {
indexFound = startingIndex + delta
}
}
}
return indexFound
}
}
search10(startingIndex:Int)
此同步方法接收一个 Int
作为参数并执行 10 个对 ConnectedDevices.getAllDetails
的并发调用。每次调用都是将 startingIndex
添加到 delta
(delta
从 0
到 9
)。
结果被同步放入同步队列,其中 numProcessed
是安全增加的。如果 found
是 true
那么 "winning" 索引 (startingIndex + delta
) 是 returned.
如果 found
永远不会变成 true
那么 nil
就是 returned.
搜索()
这是一个asych
方法。这是一个简单的 for loop
,其中 group
变量填充有 1
,然后是 11
,然后是 21
,最后是 31
.
每次调用search10
。如果它确实 return 和 Int
值被传递给 completion
闭包,否则循环继续。
如果从 search10
执行的 4 个循环没有值 return,则 nil
被传递到 completion
闭包。
用法
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
debugPrintln("Begin: \(NSDate())")
Loader().search { (result) -> () in
debugPrintln(result)
debugPrintln("End: \(NSDate())")
}
}
}
测试
40 次连续调用 ConnectedDevices.getAllDetails(...)
需要 40 * 10 = 400 seconds
.
在我的 iPhone 没有启用任何优化的模拟器中,此代码需要大约 120 seconds
。
希望这是你需要的。
P.S.
- 请注意,如果当前结果是
true
,我也会增加 numProcessed
。
- 我没有找到
isConditionTrue
的用途,所以我删除了它。
我必须根据某些条件执行一组操作,例如从数据库中获取数据,每次查询大约需要 10 秒(ConnectedDevices.getAllDetails() 需要 10 秒才能执行,return 结果)。
这可能类似于以下问题
var isConditionTrue = false
var numProcessed = 0
let dbQueue = dispatch_queue_create("dbQueue", DISPATCH_QUEUE_SERIAL)
// case 1
for i in 1...10 {
dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_UTILITY.value), 0)) {
let eachDBValue = ConnectedDevices.getAllDetails(i)
dispatch_async(dbQueue) {
if !eachDBValue {
numProcessed++
}
}
}
}
// case 2
for i in 11...20 {
dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_UTILITY.value), 0)) {
let eachDBValue = ConnectedDevices.getAllDetails(i)
dispatch_async(dbQueue) {
if !eachDBValue {
numProcessed++
}
}
}
}
// case 3
for i in 21...30 {
dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_UTILITY.value), 0)) {
let eachDBValue = ConnectedDevices.getAllDetails(i)
dispatch_async(dbQueue) {
if !ieachDBValue {
numProcessed++
}
}
}
}
// case 4
for i in 31...40 {
dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_UTILITY.value), 0)) {
let eachDBValue = ConnectedDevices.getAllDetails(i)
dispatch_async(dbQueue) {
if !eachDBValue {
numProcessed++
}
}
}
}
因此,如果在案例 1 中,如果 1 到 10 的结果为假,那么它应该转到案例 2。如果任何实例的结果为真.. 它不应该执行任何案例 2、3、4。
与情况 2 类似,如果 1 到 10 的结果为假,则应转到情况 3,否则应停止。 这一切我需要根据条件做。
这是我的解决方案
假的 ConnectedDevices class
这是我为了测试你的场景而创建的假 class。如您所见,方法 getAllDetails
确实模拟了您的数据库访问。
它等待 10 秒,然后仅当输入参数为 40
时 returns true
。这样我们就可以在最坏的情况下测试这段代码,因为所有的调用都需要完成。
class ConnectedDevices {
class func getAllDetails(i:Int) -> Bool {
sleep(10)
return i == 40
}
}
装载机class
这是将与 Grand Central Dispatch
交互的 class。
class Loader {
private var numProcessed = 0
private let dbQueue = dispatch_queue_create("dbQueue", DISPATCH_QUEUE_SERIAL)
private let utilityQueue = dispatch_get_global_queue(QOS_CLASS_UTILITY, 0)
func search(completion:(result:Int?)->()) {
dispatch_async(utilityQueue) {
for group in [1, 11, 21, 31] {
if let indexFound = self.search10(group) {
completion(result: indexFound)
return
}
}
completion(result: nil)
}
}
private func search10(startingIndex:Int) -> Int? {
var indexFound : Int?
dispatch_apply(10, utilityQueue) { (delta) -> () in
let found = ConnectedDevices.getAllDetails(startingIndex + delta)
dispatch_sync(self.dbQueue) {
self.numProcessed++ // this is increased anyway
if found {
indexFound = startingIndex + delta
}
}
}
return indexFound
}
}
search10(startingIndex:Int)
此同步方法接收一个 Int
作为参数并执行 10 个对 ConnectedDevices.getAllDetails
的并发调用。每次调用都是将 startingIndex
添加到 delta
(delta
从 0
到 9
)。
结果被同步放入同步队列,其中 numProcessed
是安全增加的。如果 found
是 true
那么 "winning" 索引 (startingIndex + delta
) 是 returned.
如果 found
永远不会变成 true
那么 nil
就是 returned.
搜索()
这是一个asych
方法。这是一个简单的 for loop
,其中 group
变量填充有 1
,然后是 11
,然后是 21
,最后是 31
.
每次调用search10
。如果它确实 return 和 Int
值被传递给 completion
闭包,否则循环继续。
如果从 search10
执行的 4 个循环没有值 return,则 nil
被传递到 completion
闭包。
用法
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
debugPrintln("Begin: \(NSDate())")
Loader().search { (result) -> () in
debugPrintln(result)
debugPrintln("End: \(NSDate())")
}
}
}
测试
40 次连续调用 ConnectedDevices.getAllDetails(...)
需要 40 * 10 = 400 seconds
.
在我的 iPhone 没有启用任何优化的模拟器中,此代码需要大约 120 seconds
。
希望这是你需要的。
P.S.
- 请注意,如果当前结果是
true
,我也会增加numProcessed
。 - 我没有找到
isConditionTrue
的用途,所以我删除了它。