প্রথমত, থ্রেড এবং সারিগুলির মধ্যে পার্থক্য এবং জিসিডি আসলে কী করে তা জানা গুরুত্বপূর্ণ। যখন আমরা প্রেরণের সারিগুলি (জিসিডি এর মাধ্যমে) ব্যবহার করি, আমরা সত্যই কুইন্ডিং করি, থ্রেডিং না। ডিসপ্যাচ কাঠামোটি বিশেষভাবে আমাদের থ্রেডিং থেকে দূরে সরিয়ে দেওয়ার জন্য ডিজাইন করা হয়েছিল, কারণ অ্যাপল স্বীকার করেছেন যে "সঠিক থ্রেডিং সমাধান কার্যকর করা [যদি] [কখনও কখনও] অর্জন করা অসম্ভব না হয় তবে" অত্যন্ত কঠিন হয়ে উঠতে পারে। " অতএব, একই সাথে কার্য সম্পাদন করতে (যে কাজগুলি আমরা UI হিমায়িত করতে চাই না), আমাদের কেবলমাত্র সেই কাজগুলির একটি সারি তৈরি করা এবং এটি জিসিডির কাছে হস্তান্তর করতে হবে। এবং জিসিডি সম্পর্কিত থ্রেডিংয়ের সমস্ত পরিচালনা করে। অতএব, আমরা যা করছি তা সত্যিই সারিবদ্ধ।
তাত্ক্ষণিকভাবে জানা দ্বিতীয় জিনিসটি কোনও কাজটি কী। একটি কাজ হ'ল এই কাতারি ব্লকের কোডগুলি (সারির মধ্যে নয়, কারণ আমরা একটি সারিতে কিছু সময় জিনিসগুলিতে যুক্ত করতে পারি তবে বন্ধ করার মধ্যে যেখানে আমরা এটি সারিতে যুক্ত করেছি)। কোনও কাজকে কখনও কখনও ব্লক হিসাবে চিহ্নিত করা হয় এবং একটি ব্লককে কখনও কখনও একটি কার্য বলে উল্লেখ করা হয় (তবে সেগুলি সাধারণত কার্য হিসাবে বিশেষত সুইফ্ট সম্প্রদায় হিসাবে পরিচিত)। এবং যতই বা সামান্য কোডই নয়, কোঁকড়ানো বন্ধনীগুলির মধ্যে থাকা সমস্ত কোডকে একটি একক কাজ হিসাবে বিবেচনা করা হয়:
serialQueue.async {
// this is one task
// it can be any number of lines with any number of methods
}
serialQueue.async {
// this is another task added to the same queue
// this queue now has two tasks
}
এবং এটি সুস্পষ্টভাবে উল্লেখ করে যে সমকালীন অর্থ অন্য জিনিসগুলির সাথে একই সময়ে হয় এবং সিরিয়ালটির অর্থ একের পর এক (কখনও কখনও একই সময়ে হয় না)। কিছু সিরিয়ালিয়াল করার জন্য, বা সিরিয়ালে কিছু রাখার অর্থ কেবল বাম থেকে ডানে, উপরে থেকে নীচে, নিরবচ্ছিন্নভাবে ক্রমানুসারে শুরু থেকে চালানো।
দুটি ধরণের সারি রয়েছে, সিরিয়াল এবং সমবর্তী, তবে সমস্ত সারি একে অপরের সাথে সামঞ্জস্যপূর্ণ । আপনি যে কোনও কোড "পটভূমিতে" চালাতে চান তার অর্থ আপনি এটি অন্য থ্রেড (সাধারণত মূল থ্রেড) সহ একযোগে চালাতে চান to সুতরাং, পাঠানো সারি, সিরিয়াল বা সমবর্তী, তাদের কাজগুলি অন্যান্য সারির সাথে একই সাথে সম্পাদন করে । কোনও ক্রমিক (সিরিয়াল কাতারে) দ্বারা সম্পাদিত সিরিয়ালাইজেশন কেবল সেই একক [সিরিয়াল] প্রেরণের সারিতে থাকা কাজগুলির সাথে করতে হবে (যেমন উপরের উদাহরণে যেখানে একই সিরিয়াল সারির মধ্যে দুটি কাজ রয়েছে; সেই কাজগুলি একের পরে কার্যকর করা হবে) অন্য, একসাথে কখনও না)।
সিরিয়াল কোয়েস (প্রায়শই প্রাইভেট প্রেরণের সারি হিসাবে পরিচিত) এগুলি নির্দিষ্ট কাতারে যুক্ত হওয়ার সাথে সাথে শুরু করার আগে একবারে কার্য সম্পাদনের গ্যারান্টি দেয়। প্রেরণের সারিতে আলোচনার যে কোনও জায়গায় এটি সিরিয়ালাইজেশনের একমাত্র গ্যারান্টি- নির্দিষ্ট সিরিয়াল সারিটির মধ্যে নির্দিষ্ট কাজগুলি সিরিয়ালে চালানো হয় in সিরিয়াল কাতগুলি তবে অন্য ক্রমিক কাতারে একই সাথে চলতে পারে যদি সেগুলি পৃথক সারিতে থাকে কারণ, আবার, সমস্ত কাতাগুলি একে অপরের সাথে সামঞ্জস্যপূর্ণ। সমস্ত কাজ পৃথক থ্রেডে চলে তবে প্রতিটি কাজ একই থ্রেডে চালানোর গ্যারান্টিযুক্ত নয় (গুরুত্বপূর্ণ নয়, তবে এটি জানতে আগ্রহী)। এবং আইওএস ফ্রেমওয়ার্কটি কোনও ব্যবহারের জন্য প্রস্তুত সিরিয়াল সারি নিয়ে আসে না, আপনাকে অবশ্যই এটি তৈরি করতে হবে। ব্যক্তিগত (অ-গ্লোবাল) সারিগুলি ডিফল্টরূপে সিরিয়াল হয় তাই সিরিয়াল সারি তৈরি করতে:
let serialQueue = DispatchQueue(label: "serial")
আপনি এর বৈশিষ্ট্যযুক্ত সম্পত্তিটির মাধ্যমে এটিকে একই সাথে তৈরি করতে পারেন:
let concurrentQueue = DispatchQueue(label: "concurrent", attributes: [.concurrent])
তবে এই মুহুর্তে, আপনি যদি ব্যক্তিগত কাতারে অন্য কোনও বৈশিষ্ট্য যুক্ত না করেন, অ্যাপল আপনাকে কেবলমাত্র প্রস্তুত রেখাগুলি বিশ্বব্যাপী সারিগুলির মধ্যে একটি ব্যবহার করুন (যা সমস্ত সমবর্তী) recommend এই উত্তরের নীচে, আপনি সিরিয়াল সারি তৈরির জন্য আরেকটি উপায় দেখতে পাবেন (লক্ষ্য সম্পত্তি ব্যবহার করে), এটি অ্যাপল কীভাবে এটি করার পরামর্শ দেয় (আরও দক্ষ সংস্থান ব্যবস্থাপনার জন্য)। তবে আপাতত, এটির লেবেলই যথেষ্ট।
কনক্যুরেন্ট প্রশ্নগুলি (প্রায়শই বিশ্বব্যাপী প্রেরণের সারি হিসাবে পরিচিত) একসাথে কার্য সম্পাদন করতে পারে; কর্ম, কিন্তু, গ্যারান্টী আছে সূচনা যাতে তারা নির্দিষ্ট সারিতে যোগ হলো, কিন্তু সিরিয়াল সারিগুলি মতো কিউ দ্বিতীয় কাজটি শুরু করার আগে প্রথম ফিনিস কাজের জন্য অপেক্ষা করে না। টাস্ক (সিরিয়াল সারি যেমন) স্বতন্ত্র থ্রেডে চালিত হয় এবং (সিরিয়াল সারিগুলির মতো) প্রতিটি কাজ একই থ্রেডে চালানোর গ্যারান্টিযুক্ত নয় (গুরুত্বপূর্ণ নয় তবে জানতে আগ্রহী)। এবং আইওএস ফ্রেমওয়ার্কটি ব্যবহারের জন্য চারটি প্রস্তুত সমবর্তী সারির সাথে আসে। আপনি উপরের উদাহরণটি ব্যবহার করে বা অ্যাপলের গ্লোবাল সারিগুলির মধ্যে একটি (যা সাধারণত প্রস্তাবিত হয়) ব্যবহার করে একটি একযোগে সারি তৈরি করতে পারেন:
let concurrentQueue = DispatchQueue.global(qos: .default)
রিটেন-সিসিল রিসার্স্ট্যান্ট: প্রেরণ সারিগুলি রেফারেন্স-গণনা করা অবজেক্টস তবে আপনাকে বৈশ্বিক সারিবদ্ধ করার কারণে বিশ্বব্যাপী সারিগুলি ধরে রাখতে এবং ছাড়ার দরকার নেই এবং সুতরাং এটি ধরে রাখা এবং মুক্তি উপেক্ষা করা হয়। আপনি কোনও সম্পত্তিতে নিযুক্ত না করে আপনি সরাসরি বিশ্বব্যাপী সারিতে অ্যাক্সেস করতে পারেন।
সারিগুলি প্রেরণের দুটি উপায় রয়েছে: একযোগে এবং অবিচ্ছিন্নভাবে।
SYNC DISPATCHING এর অর্থ হ'ল যেখানে সারিটি প্রেরণ করা হয়েছিল সেই থ্রেডটি (কলিং থ্রেড) সারি প্রেরণের পরে বিরতি দেয় এবং পুনরায় শুরু হওয়ার আগে সম্পাদন শেষ করার জন্য ue কাতার ব্লকের কার্যটির জন্য অপেক্ষা করে। একযোগে প্রেরণ করতে:
DispatchQueue.global(qos: .default).sync {
// task goes in here
}
ASYNC DISPATCHING এর অর্থ হল যে সারিটি প্রেরণ করার পরে কলিং থ্রেড চলতে থাকে এবং সেই কাতার ব্লকের কার্য সম্পাদনের জন্য অপেক্ষা না করে। অবিচ্ছিন্নভাবে প্রেরণ:
DispatchQueue.global(qos: .default).async {
// task goes in here
}
এখন কেউ ভাবতে পারে সিরিয়ালে কোনও কাজ সম্পাদন করার জন্য একটি সিরিয়াল সারি ব্যবহার করা উচিত এবং এটি ঠিক ঠিক নয়। সিরিয়ালে একাধিক টাস্ক সম্পাদন করতে একটি সিরিয়াল সারি ব্যবহার করা উচিত, তবে সমস্ত টাস্ক (নিজেরাই বিচ্ছিন্ন) সিরিয়ালে চালানো হয়। এই উদাহরণ বিবেচনা করুন:
whichQueueShouldIUse.syncOrAsync {
for i in 1...10 {
print(i)
}
for i in 1...10 {
print(i + 100)
}
for i in 1...10 {
print(i + 1000)
}
}
আপনি কীভাবে এই সিরিয়ালটি (সিরিয়াল বা সমবর্তী) কনফিগার বা প্রেরণ (সিঙ্ক বা অ্যাসিঙ্ক) করেন না কেন, এই কাজটি সর্বদা সিরিয়ালে কার্যকর করা হবে। তৃতীয় লুপটি কখনই দ্বিতীয় লুপের আগে চলবে না এবং দ্বিতীয় লুপ কখনই প্রথম লুপের আগে চলবে না। এটি কোনও প্রেরণ ব্যবহার করে যে কোনও কাতারে সত্য। এটি যখন আপনি একাধিক টাস্ক এবং / অথবা সারিগুলি প্রবর্তন করেন যেখানে সিরিয়াল এবং সম্মতিটি সত্যই কার্যকর হয়।
এই দুটি সারি বিবেচনা করুন, একটি সিরিয়াল এবং একটি সমবর্তী:
let serialQueue = DispatchQueue(label: "serial")
let concurrentQueue = DispatchQueue.global(qos: .default)
বলুন আমরা অ্যাসিঙ্কে দুটি সমবর্তী কাতাগুলি প্রেরণ করেছি:
concurrentQueue.async {
for i in 1...5 {
print(i)
}
}
concurrentQueue.async {
for i in 1...5 {
print(i + 100)
}
}
1
101
2
102
103
3
104
4
105
5
তাদের আউটপুটটি ঝাঁপিয়ে পড়েছে (আশানুরূপ হিসাবে) তবে লক্ষ্য করুন যে প্রতিটি সারি সিরিয়ালে তার নিজস্ব কাজ সম্পাদন করেছে। এটি কনক্যুরেন্সির সর্বাধিক প্রাথমিক উদাহরণ - একই সারিতে ব্যাকগ্রাউন্ডে একই সময়ে দুটি কাজ চলছে। এবার প্রথম সিরিয়ালটি করা যাক:
serialQueue.async {
for i in 1...5 {
print(i)
}
}
concurrentQueue.async {
for i in 1...5 {
print(i + 100)
}
}
101
1
2
102
3
103
4
104
5
105
সিরিয়ালে প্রথম সারিতে মৃত্যুদণ্ড কার্যকর করার কথা নয়? এটি ছিল (এবং দ্বিতীয়টিও তাই)। ব্যাকগ্রাউন্ডে আর যা কিছু ঘটেছে তা সারিতে কোনও উদ্বেগের বিষয় নয়। আমরা সিরিয়ালে ক্রিউ চালানোর জন্য সিরিয়ালটি বললাম এবং তা হয়ে গেল ... তবে আমরা কেবল এটির একটি কাজ দিয়েছি। এখন এটি দুটি কাজ দেওয়া যাক:
serialQueue.async {
for i in 1...5 {
print(i)
}
}
serialQueue.async {
for i in 1...5 {
print(i + 100)
}
}
1
2
3
4
5
101
102
103
104
105
এবং এটি সিরিয়ালাইজেশনের সবচেয়ে বুনিয়াদি (এবং কেবলমাত্র সম্ভব) উদাহরণ - একই সারিতে ব্যাকগ্রাউন্ডে (মূল থ্রেডে) সিরিয়ালে দুটি কাজ (একের পর এক) চলছে। তবে যদি আমরা তাদের দুটি পৃথক ক্রমিক কাতারে পরিণত করি (কারণ উপরের উদাহরণে তারা একই সারি) তবে তাদের আউটপুটটি আবারও ঝাঁকুনির মধ্যে পড়ে:
serialQueue.async {
for i in 1...5 {
print(i)
}
}
serialQueue2.async {
for i in 1...5 {
print(i + 100)
}
}
1
101
2
102
3
103
4
104
5
105
এবং এটিই আমি বলতে চাইছিলাম যখন আমি বলেছিলাম সমস্ত সারি একে অপরের সাথে সামঞ্জস্যপূর্ণ। এটি একই সাথে তাদের কাজগুলি সম্পাদন করে এমন দুটি সিরিয়াল কাতারে (কারণ তারা পৃথক সারি)। একটি সারিটি অন্যান্য সারিগুলি জানে না বা যত্ন করে না। এখন দুটি সিরিয়াল কাতারে ফিরে যেতে দিন (একই সারির) এবং তৃতীয় সারি যুক্ত করুন, সমবর্তী:
serialQueue.async {
for i in 1...5 {
print(i)
}
}
serialQueue.async {
for i in 1...5 {
print(i + 100)
}
}
concurrentQueue.async {
for i in 1...5 {
print(i + 1000)
}
}
1
2
3
4
5
101
102
103
104
105
1001
1002
1003
1004
1005
এ ধরণের অপ্রত্যাশিত, কেন ক্রমিক সারিবদ্ধ ক্রিয়াকলাপগুলি সঞ্চালনের আগে শেষ হওয়ার অপেক্ষা করেছিল? এটি একমত নয়। আপনার খেলার মাঠ একটি আলাদা আউটপুট প্রদর্শন করতে পারে তবে আমার এটি দেখিয়েছে। এবং এটি এটি দেখিয়েছিল কারণ জিসিডি এর কাজটি তাড়াতাড়ি সম্পাদন করার জন্য আমার সমবর্তী সারির অগ্রাধিকার যথেষ্ট ছিল না। সুতরাং আমি যদি সমস্ত কিছু একই রাখি তবে গ্লোবাল কিউয়ের কিউএস পরিবর্তন করি (এর পরিষেবার মান, যা কেবল কাতারের অগ্রাধিকার স্তর) let concurrentQueue = DispatchQueue.global(qos: .userInteractive)
, তবে আউটপুটটি প্রত্যাশা অনুযায়ী:
1
1001
1002
1003
2
1004
1005
3
4
5
101
102
103
104
105
দুটি সিরিয়াল সারি ক্রিয়াকলাপে (যেমনটি প্রত্যাশা করা) কাজ সম্পাদন করে এবং সমবর্তী সারির কাজটি দ্রুত সম্পাদন করে কারণ এটি একটি উচ্চ অগ্রাধিকার স্তর (একটি উচ্চ কিউএস, বা পরিষেবার মান) দেওয়া হয়েছিল।
আমাদের প্রথম মুদ্রণের উদাহরণের মতো দুটি সমবর্তী কাতারে একটি ঝাঁকুনিযুক্ত প্রিন্টআউট (প্রত্যাশার মতো) দেখায়। তাদের সিরিয়ালে ঝরঝরে মুদ্রণের জন্য, আমাদের উভয়কে একই ক্রমিক কাতারে তৈরি করতে হবে (সেই সারির একই উদাহরণ, পাশাপাশি, কেবল একই লেবেল নয়) । তারপরে প্রতিটি কাজ অন্যটির সাথে সম্মানের সাথে সিরিয়ালে চালানো হয়। তবে সিরিয়ালে মুদ্রণের জন্য তাদের আরেকটি উপায় হ'ল তাদের উভয়কে একযোগে রাখা তবে তাদের প্রেরণের পদ্ধতিটি পরিবর্তন করা:
concurrentQueue.sync {
for i in 1...5 {
print(i)
}
}
concurrentQueue.async {
for i in 1...5 {
print(i + 100)
}
}
1
2
3
4
5
101
102
103
104
105
মনে রাখবেন, সিঙ্ক প্রেরণের কেবল অর্থ হ'ল কলিং থ্রেড এগিয়ে যাওয়ার আগে সারিতে কাজ শেষ না হওয়া পর্যন্ত অপেক্ষা করে। স্পষ্টতই এখানে সতর্কবাণীটি হ'ল কলিং থ্রেড হিমশীতল হওয়া পর্যন্ত প্রথম কাজটি শেষ না হওয়া পর্যন্ত, আপনি ইউআই কীভাবে সম্পাদন করতে চান তা নাও হতে পারে।
এবং এই কারণেই আমরা নিম্নলিখিতটি করতে পারি না:
DispatchQueue.main.sync { ... }
এটি সারি এবং প্রেরণ পদ্ধতির একমাত্র সম্ভাব্য সংমিশ্রণ যা আমরা সম্পাদন করতে পারি না the মূল কাতারে সিঙ্ক্রোনাস প্রেরণ। এবং এর কারণ আমরা কোঁকড়া ধনুর্বন্ধনী মধ্যে কাজ সম্পাদন না করা পর্যন্ত আমরা মূল সারিটি হিমায়িত করতে বলছি ... যা আমরা মূল কাতারে প্রেরণ করেছি, যা আমরা কেবল হিমশীতল করে দিয়েছি। একে ডেডলক বলা হয়। কোনও খেলার মাঠে এটি ক্রিয়াতে দেখতে:
DispatchQueue.main.sync { // stop the main queue and wait for the following to finish
print("hello world") // this will never execute on the main queue because we just stopped it
}
// deadlock
একটি উল্লেখযোগ্য জিনিস উল্লেখ করার পরে সম্পদ resources যখন আমরা কোনও কাতাকে একটি কার্য দিই, জিসিডি তার অভ্যন্তরীণভাবে পরিচালিত পুল থেকে একটি উপলব্ধ সারি খুঁজে পায়। এই উত্তরটি লেখার ক্ষেত্রে, প্রতি কোষে 64 টি সারি উপলব্ধ। এটি অনেকটা মনে হলেও এগুলি দ্রুত গ্রাস করা যায়, বিশেষত তৃতীয় পক্ষের লাইব্রেরি, বিশেষত ডাটাবেস ফ্রেমওয়ার্কগুলি দ্বারা। এই কারণে, অ্যাপলের সারি ব্যবস্থাপনা সম্পর্কে সুপারিশ রয়েছে (নীচের লিঙ্কগুলিতে উল্লিখিত); এক হচ্ছে:
ব্যক্তিগত সমকালীন সারি তৈরি করার পরিবর্তে বিশ্বব্যাপী একত্রে প্রেরণের জন্য একটি সারিতে কাজ জমা দিন। ক্রমিক কাজগুলির জন্য, আপনার ক্রমিক সারির লক্ষ্যটি বিশ্বব্যাপী সমবর্তী সারির একটিতে সেট করুন।
এইভাবে, থ্রেড তৈরির পৃথক সারির সংখ্যা হ্রাস করার সময় আপনি সারিটির ক্রমিক ক্রিয়াকলাপটি বজায় রাখতে পারেন।
এটি করার জন্য, এগুলি তৈরি করার পরিবর্তে আমরা এর আগে তৈরি করেছি (যা আপনি এখনও পারেন), অ্যাপল এই জাতীয় সিরিয়াল সারি তৈরি করার পরামর্শ দেয়:
let serialQueue = DispatchQueue(label: "serialQueue", qos: .default, attributes: [], autoreleaseFrequency: .inherit, target: .global(qos: .default))
আরও পড়ার জন্য, আমি নিম্নলিখিতটি সুপারিশ করছি:
https://developer.apple.com/library/archive/documentation/General/Conceptual/ConcurrencyProgrammingGuide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40008091-CH1-SW1
https://developer.apple.com/documentation/dispatch/dispatchqueue