Ответ 1
Синхронный подход
Если мы выполняем каждый вызов Ping.getIPAddress(str)
только после того, как предыдущий закончен, нам нужно ждать (3 секунды * 256) = 768 секунд.
Асинхронный подход
С другой стороны, мы можем выполнить несколько одновременных вызовов Ping.getIPAddress(str)
.
Поддельный класс Ping
Это класс, который я создал для проверки вашей функции.
class Ping {
class func getIPAddress(str:String) -> Bool {
sleep(3)
return str == "163.289.2.255"
}
}
Как вы видите, класс ожидает 3 секунды (для имитации вашего сценария), а затем возвращает true
, только если прошедший ip
равен 163.289.2.255
. Это позволяет мне воспроизвести худший сценарий.
Решение
Это класс, который я подготовил
class QuantumComputer {
func search(completion:(existingIP:String?) -> ()) {
var resultFound = false
var numProcessed = 0
let serialQueue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL)
for i in 0...255 {
dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_UTILITY.value), 0)) {
var ip = "163.289.2." + "\(i)"
let foundThisOne = Ping.getIPAddress(ip)
dispatch_async(serialQueue) {
if !resultFound {
resultFound = foundThisOne
numProcessed++
if resultFound {
completion(existingIP:ip)
} else if numProcessed == 256 {
completion(existingIP: nil)
}
}
}
}
}
}
}
Класс выполняет 256 асинхронных вызовов до Ping.getIPAddress(...)
.
Результаты из 256 закрытий асинхронов обрабатываются этим кодом:
dispatch_async(serialQueue) {
if !resultFound {
resultFound = foundThisOne
numProcessed++
if resultFound {
completion(existingIP:ip)
} else if numProcessed == 256 {
completion(existingIP: nil)
}
}
}
В моей очереди serialQueue
выполняется предыдущий блок кода (от строки № 2 до # 9). Здесь 256 отдельных закрытий работают синхронно.
- Это важно для обеспечения последовательного доступа к переменным
resultFound
иnumProcessed
; - с другой стороны, это не проблема с точки зрения производительности, поскольку этот код довольно быстрый (всего несколько арифметических операций)
Test
И вот как я называю это из стандартного ViewController.
class ViewController: UIViewController {
var computer = QuantumComputer()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
debugPrintln(NSDate())
computer.search { (existingIP) -> () in
debugPrintln("existingIP: \(existingIP)")
debugPrintln(NSDate())
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Выводы
Наконец, это результат, когда я тестирую его на симуляторе iOS. Напомним, что это худший сценарий (поскольку последний проверенный номер является допустимым IP-адресом).
2015-09-04 20:56:17 +0000
"existingIP: Optional(\"163.289.2.255\")"
2015-09-04 20:56:29 +0000
Это всего лишь 12 секунд!
Надеюсь, что это поможет.