Mit Swift 5.1 bietet Grand Central Dispatch viele Möglichkeiten, um Ihr Problem zu lösen. Je nach Bedarf können Sie eines der sieben Muster auswählen , die in den folgenden Spielplatzausschnitten gezeigt werden.
Im Apple Developer Concurrency Programming Guide wird Folgendes beschriebenDispatchGroup
:
Dispatch-Gruppen sind eine Möglichkeit, einen Thread zu blockieren, bis eine oder mehrere Aufgaben ausgeführt sind. Sie können dieses Verhalten an Orten verwenden, an denen Sie erst dann Fortschritte erzielen können, wenn alle angegebenen Aufgaben abgeschlossen sind. Nachdem Sie beispielsweise mehrere Aufgaben zum Berechnen einiger Daten gesendet haben, können Sie eine Gruppe verwenden, um auf diese Aufgaben zu warten und die Ergebnisse dann zu verarbeiten, wenn sie erledigt sind.
import Foundation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
let queue = DispatchQueue(label: "com.company.app.queue", attributes: .concurrent)
let group = DispatchGroup()
queue.async(group: group) {
print("#1 started")
Thread.sleep(forTimeInterval: 5)
print("#1 finished")
}
queue.async(group: group) {
print("#2 started")
Thread.sleep(forTimeInterval: 2)
print("#2 finished")
}
group.notify(queue: queue) {
print("#3 finished")
}
/*
prints:
#1 started
#2 started
#2 finished
#1 finished
#3 finished
*/
# 2. Verwenden von DispatchGroup
, DispatchGroup
's wait()
, DispatchGroup
' s enter()
und DispatchGroup
'sleave()
import Foundation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
let queue = DispatchQueue(label: "com.company.app.queue", attributes: .concurrent)
let group = DispatchGroup()
group.enter()
queue.async {
print("#1 started")
Thread.sleep(forTimeInterval: 5)
print("#1 finished")
group.leave()
}
group.enter()
queue.async {
print("#2 started")
Thread.sleep(forTimeInterval: 2)
print("#2 finished")
group.leave()
}
queue.async {
group.wait()
print("#3 finished")
}
/*
prints:
#1 started
#2 started
#2 finished
#1 finished
#3 finished
*/
Beachten Sie, dass Sie auch DispatchGroup
wait()
mit DispatchQueue
async(group:qos:flags:execute:)
oder mischen DispatchGroup
enter()
und DispatchGroup
leave()
mit mischen können DispatchGroup
notify(qos:flags:queue:execute:)
.
Grand Central Dispatch Tutorial für Swift 4: Teil 1/2 Artikel von Raywenderlich.com enthält eine Definition für Barrieren :
Versandbarrieren sind eine Gruppe von Funktionen, die bei der Arbeit mit gleichzeitigen Warteschlangen als serieller Engpass fungieren. Wenn Sie eine DispatchWorkItem
an eine Versandwarteschlange senden , können Sie Flags setzen, um anzugeben, dass dies das einzige Element sein soll, das für diese bestimmte Zeit in der angegebenen Warteschlange ausgeführt wird. Dies bedeutet, dass alle Elemente, die vor der Versandbarriere an die Warteschlange gesendet wurden, abgeschlossen sein müssen, bevor die DispatchWorkItem
Ausführung ausgeführt wird.
Verwendung:
import Foundation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
let queue = DispatchQueue(label: "com.company.app.queue", attributes: .concurrent)
queue.async {
print("#1 started")
Thread.sleep(forTimeInterval: 5)
print("#1 finished")
}
queue.async {
print("#2 started")
Thread.sleep(forTimeInterval: 2)
print("#2 finished")
}
queue.async(flags: .barrier) {
print("#3 finished")
}
/*
prints:
#1 started
#2 started
#2 finished
#1 finished
#3 finished
*/
import Foundation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
let queue = DispatchQueue(label: "com.company.app.queue", attributes: .concurrent)
queue.async {
print("#1 started")
Thread.sleep(forTimeInterval: 5)
print("#1 finished")
}
queue.async {
print("#2 started")
Thread.sleep(forTimeInterval: 2)
print("#2 finished")
}
let dispatchWorkItem = DispatchWorkItem(qos: .default, flags: .barrier) {
print("#3 finished")
}
queue.async(execute: dispatchWorkItem)
/*
prints:
#1 started
#2 started
#2 finished
#1 finished
#3 finished
*/
# 5. Verwenden von DispatchSemaphore
, DispatchSemaphore
's wait()
und DispatchSemaphore
' ssignal()
Soroush Khanlou schrieb die folgenden Zeilen im Blog-Beitrag des GCD-Handbuchs :
Mit einem Semaphor können wir einen Thread für eine beliebige Zeitspanne blockieren, bis ein Signal von einem anderen Thread gesendet wird. Semaphoren sind wie der Rest der GCD threadsicher und können von überall aus ausgelöst werden. Semaphore können verwendet werden, wenn es eine asynchrone API gibt, die Sie synchronisieren müssen, die Sie jedoch nicht ändern können.
Die Apple Developer API-Referenz enthält auch die folgende Diskussion für den DispatchSemaphore
init(value:)
Initialisierer:
Das Übergeben von Null für den Wert ist nützlich, wenn zwei Threads den Abschluss eines bestimmten Ereignisses abgleichen müssen. Das Übergeben eines Werts größer als Null ist nützlich, um einen endlichen Ressourcenpool zu verwalten, bei dem die Poolgröße dem Wert entspricht.
Verwendung:
import Foundation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
let queue = DispatchQueue(label: "com.company.app.queue", attributes: .concurrent)
let semaphore = DispatchSemaphore(value: 0)
queue.async {
print("#1 started")
Thread.sleep(forTimeInterval: 5)
print("#1 finished")
semaphore.signal()
}
queue.async {
print("#2 started")
Thread.sleep(forTimeInterval: 2)
print("#2 finished")
semaphore.signal()
}
queue.async {
semaphore.wait()
semaphore.wait()
print("#3 finished")
}
/*
prints:
#1 started
#2 started
#2 finished
#1 finished
#3 finished
*/
In der Apple Developer API-Referenz heißt es über OperationQueue
:
Operationswarteschlangen verwenden die libdispatch
Bibliothek (auch als Grand Central Dispatch bezeichnet), um die Ausführung ihrer Operationen zu initiieren.
Verwendung:
import Foundation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
let operationQueue = OperationQueue()
let blockOne = BlockOperation {
print("#1 started")
Thread.sleep(forTimeInterval: 5)
print("#1 finished")
}
let blockTwo = BlockOperation {
print("#2 started")
Thread.sleep(forTimeInterval: 2)
print("#2 finished")
}
let blockThree = BlockOperation {
print("#3 finished")
}
blockThree.addDependency(blockOne)
blockThree.addDependency(blockTwo)
operationQueue.addOperations([blockThree, blockTwo, blockOne], waitUntilFinished: false)
/*
prints:
#1 started
#2 started
#2 finished
#1 finished
#3 finished
or
#2 started
#1 started
#2 finished
#1 finished
#3 finished
*/
import Foundation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
let operationQueue = OperationQueue()
let blockOne = BlockOperation {
print("#1 started")
Thread.sleep(forTimeInterval: 5)
print("#1 finished")
}
let blockTwo = BlockOperation {
print("#2 started")
Thread.sleep(forTimeInterval: 2)
print("#2 finished")
}
operationQueue.addOperations([blockTwo, blockOne], waitUntilFinished: false)
operationQueue.addBarrierBlock {
print("#3 finished")
}
/*
prints:
#1 started
#2 started
#2 finished
#1 finished
#3 finished
or
#2 started
#1 started
#2 finished
#1 finished
#3 finished
*/