iOS
जीसीडी (ग्रैंड सेंट्रल डिस्पैच)
खोज…
परिचय
ग्रैंड सेंट्रल डिस्पैच (जीसीडी) मल्टीथ्रेडिंग के लिए एप्पल का जवाब है। यह कतारों में सिंक्रोनस या एसिंक्रोनसली कार्य करने के लिए एक हल्का ढांचा है और पर्दे के पीछे आपके लिए सीपीयू थ्रेड्स संभालता है।
संबंधित विषय: चिंता
प्रेषण कतार बनाएँ
आप dispatch_queue_create
का उपयोग करके अपनी खुद की कतार बना सकते हैं
उद्देश्य सी
dispatch_queue_t queue = dispatch_queue_create("com.example.myqueue", DISPATCH_QUEUE_SERIAL);
तीव्र
// Before Swift 3
let queue = dispatch_queue_create("com.example.myqueue", DISPATCH_QUEUE_SERIAL)
// Swift 3
let queue = DispatchQueue(label: "com.example.myqueue") //default is serial queue, unless .concurrent is specified as an attribute otherwise
मुख्य कतार हो रही है
मुख्य कतार प्रेषण कतार है जिसमें सभी यूआई अपडेट होते हैं और यूआई परिवर्तनों वाले कोड को रखा जाता है।
NSURLSession
जैसी अतुल्यकालिक प्रक्रिया के पूरा होने पर UI को अपडेट करने के लिए आपको मुख्य कतार में NSURLSession
synchronous
और asynchronous
कॉल की दो मुख्य कतारें हैं। जब आप किसी चीज़ को synchronously
, तो इसका मतलब है कि उस ऑपरेशन को शुरू करने वाला धागा कार्य को जारी रखने से पहले पूरा होने की प्रतीक्षा करेगा। Asynchronous
मतलब है कि यह इंतजार नहीं करेगा।
कोड उद्देश्य-सी
Synchronous
मुख्य कतार कॉल
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
Asynchronous
मुख्य कतार कॉल
dispatch_async(dispatch_get_main_queue(), ^{
// do work here to Usually to update the User Interface
});
स्विफ्ट 3
Asynchronous
मुख्य कतार कॉल
DispatchQueue.main.async {
}
Synchronous
मुख्य कतार कॉल
DispatchQueue.main.sync {
}
डिस्पैच ग्रुप
डिस्पैचग्रुप काम के कुल तुल्यकालन के लिए अनुमति देता है। आप कई अलग-अलग कार्य आइटम सबमिट करने और उन्हें ट्रैक करने के लिए उपयोग कर सकते हैं जब वे सभी पूर्ण हो जाते हैं, भले ही वे अलग-अलग कतारों पर चल सकें। यह व्यवहार तब सहायक हो सकता है जब प्रगति तब तक नहीं की जा सकती जब तक कि सभी निर्दिष्ट कार्य पूरे नहीं हो जाते।
एक परिदृश्य जब यह उपयोगी हो सकता है यदि आपके पास कई webservice कॉल हैं जो सभी को जारी रखने से पहले समाप्त करने की आवश्यकता है। उदाहरण के लिए, आपको डेटा के कई सेट डाउनलोड करने होंगे जो किसी फ़ंक्शन द्वारा संसाधित किए जाने की आवश्यकता होती है। आपको सभी प्राप्त डेटा को संसाधित करने के लिए फ़ंक्शन को कॉल करने से पहले सभी वेब सेवाओं के पूरा होने का इंतजार करना होगा।
स्विफ्ट 3
func doLongTasksAndWait () {
print("starting long running tasks")
let group = DispatchGroup() //create a group for a bunch of tasks we are about to do
for i in 0...3 { //launch a bunch of tasks (eg a bunch of webservice calls that all need to be finished before proceeding to the next ViewController)
group.enter() //let the group know that something is being added
DispatchQueue.global().async { //run tasks on a background thread
sleep(arc4random() % 4) //do some long task eg webservice or database lookup (here we are just sleeping for a random amount of time for demonstration purposes)
print("long task \(i) done!")
group.leave() //let group know that the task is finished
}
}
group.wait() //will block whatever thread we are on here until all the above tasks have finished (so maybe dont use this function on your main thread)
print("all tasks done!")
}
वैकल्पिक रूप से, यदि आप समूहों को समाप्त करने के लिए इंतजार नहीं करना चाहते हैं, बल्कि सभी कार्यों को पूरा करने के बाद एक फ़ंक्शन चलाना चाहते हैं, तो group.wait()
स्थान पर notify
फ़ंक्शन का उपयोग notify
group.notify(queue: DispatchQueue.main) { //the queue: parameter is which queue this block will run on, if you need to do UI updates, use the main queue
print("all tasks done!") //this will execute when all tasks have left the group
}
उदाहरण आउटपुट:
starting long running tasks
long task 0 done!
long task 3 done!
long task 1 done!
long task 2 done!
all tasks done!
अधिक जानकारी के लिए, Apple डॉक्स या संबंधित विषय को देखें
डिस्पैच सेमाफोर
DispatchSemaphore एक पारंपरिक गिनती सेमाफोर का कुशल कार्यान्वयन प्रदान करता है, जिसका उपयोग कई निष्पादन संदर्भों में संसाधन तक पहुँच को नियंत्रित करने के लिए किया जा सकता है।
सेमाफ़ोर का उपयोग करने के लिए एक परिदृश्य हो सकता है यदि आप कुछ फ़ाइल पढ़ने / लिखने का काम कर रहे हैं, यदि एक ही समय में कई कार्य फ़ाइल से पढ़ने और लिखने की कोशिश कर रहे हैं, तो यह आपके प्रदर्शन को बढ़ा सकता है ताकि प्रत्येक कार्य को अपनी बारी का इंतजार करना पड़े ताकि I / O कंट्रोलर को ओवरबर्ड नहीं करना है।
स्विफ्ट 3
func do2TasksAtATime () {
print("starting long running tasks (2 at a time)")
let sem = DispatchSemaphore(value: 2) //this semaphore only allows 2 tasks to run at the same time (the resource count)
for i in 0...7 { //launch a bunch of tasks
DispatchQueue.global().async { //run tasks on a background thread
sem.wait() //wait here if no resources available
sleep(2) //do some long task eg file access (here we are just sleeping for a 2 seconds for demonstration purposes)
print("long task \(i) done! \(Date())")
sem.signal() //let the semaphore know this resource is now available
}
}
}
उदाहरण आउटपुट: (समय टिकटों पर ध्यान दें)
starting long running tasks (2 at a time)
long task 0 done! 2017-02-16 07:11:53 +0000
long task 1 done! 2017-02-16 07:11:53 +0000
long task 2 done! 2017-02-16 07:11:55 +0000
long task 3 done! 2017-02-16 07:11:55 +0000
long task 5 done! 2017-02-16 07:11:57 +0000
long task 4 done! 2017-02-16 07:11:57 +0000
long task 6 done! 2017-02-16 07:11:59 +0000
long task 7 done! 2017-02-16 07:11:59 +0000
अधिक जानकारी के लिए, Apple डॉक्स देखें
सीरियल बनाम कंसंट्रेट डिस्पैच क्यु
स्विफ्ट 3
सीरियल कतार
func serialQueues () {
let serialQueue = DispatchQueue(label: "com.example.serial") //default queue type is a serial queue
let start = Date ()
for i in 0...3 { //launch a bunch of tasks
serialQueue.async { //run tasks on a background thread, using our serial queue
sleep(2) //do some long task eg webservice or database lookup
let timeTaken = Date().timeIntervalSince(start)
print("serial long task \(i) done! total time taken: \(timeTaken)")
}
}
}
उदाहरण आउटपुट:
serial long task 0 done! total time taken: 2.07241100072861
serial long task 1 done! total time taken: 4.16347700357437
serial long task 2 done! total time taken: 6.23209798336029
serial long task 3 done! total time taken: 8.30682599544525
समवर्ती कतार
func concurrentQueues () {
let concurrentQueue = DispatchQueue(label: "com.example.concurrent", attributes: .concurrent) //explicitly specify the queue to be a concurrent queue
let start = Date ()
for i in 0...3 { //launch a bunch of tasks
concurrentQueue.async { //run tasks on a background thread, using our concurrent queue
sleep(2) //do some long task eg webservice or database lookup
let timeTaken = Date().timeIntervalSince(start)
print("concurrent long task \(i) done! total time taken: \(timeTaken)")
}
}
}
उदाहरण आउटपुट:
concurrent long task 3 done! total time taken: 2.07092100381851
concurrent long task 0 done! total time taken: 2.07087397575378
concurrent long task 2 done! total time taken: 2.07086700201035
concurrent long task 1 done! total time taken: 2.07089096307755
विचार-विमर्श
जैसा कि हम ऊपर दिए गए उदाहरणों से देख सकते हैं, एक क्रम कतार प्रत्येक कार्य को उसी क्रम में पूरा करेगी जिस क्रम में उन्हें कतार में प्रस्तुत किया गया है। प्रत्येक कार्य निष्पादित करने से पहले पिछले कार्य के समाप्त होने की प्रतीक्षा करेगा। समवर्ती कतार के लिए, प्रत्येक कार्य कतार में दूसरों पर इंतजार नहीं करता है और जितनी जल्दी हो सके निष्पादित करता है; लाभ यह है कि कतार पर सभी कार्य अलग-अलग थ्रेड्स पर एक ही समय पर चलेंगे, जिससे समवर्ती कतार एक सीरियल कतार से कम समय लेगी।
यदि कार्यों के निष्पादन का क्रम महत्वपूर्ण नहीं है, तो हमेशा सर्वश्रेष्ठ दक्षता के लिए एक समवर्ती कतार का उपयोग करें।