Swift 5.1では、Grand Central Dispatchが問題を解決する多くの方法を提供します。必要に応じて、次のPlaygroundスニペットに示す7つのパターンのいずれかを選択できます。
Apple Developer Concurrency Programming Guide は次のように述べていDispatchGroup
ます:
ディスパッチグループは、1つ以上のタスクの実行が完了するまでスレッドをブロックする方法です。この動作は、指定されたすべてのタスクが完了するまで進行できない場所で使用できます。たとえば、いくつかのタスクをディスパッチしてデータを計算した後、グループを使用してそれらのタスクを待機し、完了したら結果を処理します。
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
*/
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
*/
あなたも混在させることができることに注意DispatchGroup
wait()
してDispatchQueue
async(group:qos:flags:execute:)
か、ミックスDispatchGroup
enter()
し、DispatchGroup
leave()
とDispatchGroup
notify(qos:flags:queue:execute:)
。
Swift 4のGrand Central Dispatchチュートリアル:パート1/2 Raywenderlich.comの記事は、バリアの定義を示しています。
ディスパッチバリアは、同時実行キューを操作するときにシリアルスタイルのボトルネックとして機能する関数のグループです。をDispatchWorkItem
ディスパッチキューに送信するときに、フラグを設定して、その特定の時間に指定されたキューで実行される唯一のアイテムであることを示すことができます。つまり、ディスパッチバリアの前にキューに送信されたすべてのアイテムは、DispatchWorkItem
が実行される前に完了する必要があります。
使用法:
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
*/
Soroush Khanlouは次の行を書きました GCDハンドブックのブログ投稿。
セマフォを使用すると、別のスレッドからのシグナルが送信されるまで、スレッドを任意の時間ブロックできます。GCDの他の部分と同様に、セマフォはスレッドセーフであり、どこからでもトリガーできます。セマフォは、同期化する必要がある非同期APIがある場合に使用できますが、変更することはできません。
Apple Developer APIリファレンスでは、DispatchSemaphore
init(value:)
イニシャライザに関する次の説明も提供しています。
値にゼロを渡すと、2つのスレッドが特定のイベントの完了を調整する必要がある場合に役立ちます。ゼロより大きい値を渡すと、リソースの有限のプールを管理するのに役立ちます。この場合、プールサイズは値と同じです。
使用法:
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
*/
Apple Developer APIリファレンスには、OperationQueue
次のように記載されています。
操作キューは、 libdispatch
ライブラリ(Grand Central Dispatchとも呼ばれ、操作の実行を開始します。
使用法:
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
*/