ด้วย Swift 5.1, Grand Central Dispatchเสนอวิธีแก้ปัญหาของคุณได้หลายวิธี ตามความต้องการของคุณคุณสามารถเลือกหนึ่งในเจ็ดรูปแบบที่แสดงในตัวอย่างสนามเด็กเล่นต่อไปนี้
คู่มือการเขียนโปรแกรมพร้อมกันของ Developer Developer ของ Apple ระบุเกี่ยวกับDispatchGroup
:
กลุ่มการแจกจ่ายเป็นวิธีการบล็อกเธรดจนกว่าภารกิจอย่างน้อยหนึ่งภารกิจจะเสร็จสิ้น คุณสามารถใช้พฤติกรรมนี้ในสถานที่ที่คุณไม่สามารถดำเนินการได้จนกว่างานที่ระบุทั้งหมดจะเสร็จสมบูรณ์ ตัวอย่างเช่นหลังจากจัดส่งงานหลายอย่างเพื่อคำนวณข้อมูลบางอย่างคุณอาจใช้กลุ่มเพื่อรองานเหล่านั้นแล้วประมวลผลผลลัพธ์เมื่อดำเนินการเสร็จ
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:)
Grand Central Dispatch Tutorial สำหรับ Swift 4: Part 1/2บทความจาก Raywenderlich.com ให้คำจำกัดความสำหรับอุปสรรค :
Dispatch barrier เป็นกลุ่มของฟังก์ชันที่ทำหน้าที่เป็นคอขวดแบบอนุกรมเมื่อทำงานกับคิวที่เกิดขึ้นพร้อมกัน เมื่อคุณส่ง a 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 เขียนบรรทัดต่อไปนี้ในโพสต์บล็อกThe GCD Handbook :
ใช้เซมาฟอร์เราสามารถบล็อกเธรดได้ตามระยะเวลาที่กำหนดจนกว่าจะมีการส่งสัญญาณจากเธรดอื่น Semaphores เช่น GCD ส่วนที่เหลือนั้นมีความปลอดภัยต่อเธรดและสามารถถูกเรียกใช้จากที่ใดก็ได้ สามารถใช้เซมิโคลอนเมื่อมี API แบบอะซิงโครนัสที่คุณต้องทำการซิงโครนัส แต่คุณไม่สามารถแก้ไขได้
การอ้างอิง API สำหรับนักพัฒนาของ Apple ยังให้การอภิปรายต่อไปนี้สำหรับเครื่องมือDispatchSemaphore
init(value:)
เริ่มต้น:
การผ่านศูนย์สำหรับค่าจะเป็นประโยชน์สำหรับเมื่อสองเธรดจำเป็นต้องกระทบยอดความสมบูรณ์ของเหตุการณ์เฉพาะ การส่งผ่านค่าที่มากกว่าศูนย์จะมีประโยชน์สำหรับการจัดการแหล่ง จำกัด ของทรัพยากรโดยที่ขนาดกลุ่มเท่ากันกับค่า
การใช้งาน:
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
*/
การอ้างอิง API สำหรับนักพัฒนาของ Apple เกี่ยวกับ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
*/