Rust में टास्क क्यू का परिचय
\n\nटास्क क्यू कंकरेंट प्रोग्रामिंग के सबसे बुनियादी पैटर्न में से एक है। यह थ्रेड्स के बीच काम को कुशलतापूर्वक स्थानांतरित करने में मदद करता है, जिससे एप्लिकेशन आर्किटेक्चर सरल हो जाता है। Rust में, अपनी सख्त ओनरशिप सिस्टम और टाइप्स के साथ, क्यू के साथ काम करने के लिए एक विशेष दृष्टिकोण की आवश्यकता होती है, लेकिन बदले में यह अविश्वसनीय सुरक्षा और प्रदर्शन प्रदान करता है।
\n\nइस लेख में, हम सीखेंगे कि Rust में स्क्रैच से टास्क क्यू कैसे बनाएं और उपयोग करें। आप भाषा के मानक टूल्स जैसे mpsc (multi-producer, single-consumer) चैनलों के बारे में जानेंगे, और एसिंक्रोनस प्रोसेसिंग के लिए लोकप्रिय लाइब्रेरीज़ से परिचित होंगे। यह सामग्री शुरुआती डेवलपर्स के लिए है जो Rust सिंटैक्स की मूल बातें पहले से जानते हैं।
मूल बातें: टास्क क्यू क्या है और इसकी आवश्यकता क्यों है
\n\nटास्क क्यू एक डेटा स्ट्रक्चर है जो FIFO (First In, First Out) सिद्धांत पर काम करता है। मल्टीथ्रेडिंग के संदर्भ में, यह कुछ थ्रेड्स (प्रोड्यूसर) को कार्य जोड़ने और दूसरों (कंज्यूमर) को उन्हें लेने और निष्पादित करने की अनुमति देता है।
\n\nटास्क क्यू के मुख्य लाभ:
\n\n- \n
- जिम्मेदारी का विभाजन — कार्य उत्पन्न करने का तर्क उनके निष्पादन से अलग हो जाता है। \n
- लोड बैलेंसिंग — समानांतर प्रोसेसिंग के लिए कई कंज्यूमर थ्रेड चलाए जा सकते हैं। \n
- डेटा फ्लो प्रबंधन — क्यू पीक लोड को स्मूथ करता है, सिस्टम ओवरलोड को रोकता है। \n
- आसान परीक्षण — प्रत्येक घटक को अलग-अलग टेस्ट किया जा सकता है। \n
Rust में, स्टैंडर्ड लाइब्रेरी एक रिसीवर के साथ चैनल बनाने के लिए मॉड्यूल std::sync::mpsc प्रदान करती है। यह शुरुआत करने के लिए एक आदर्श टूल है।
mpsc के साथ एक सरल क्यू बनाना
\n\nचलिए एक बुनियादी उदाहरण से शुरू करते हैं: एक प्रोड्यूसर नंबर भेजता है, एक कंज्यूमर उन्हें प्रोसेस करता है।
\n\nuse std::sync::mpsc;\nuse std::thread;\nuse std::time::Duration;\n\nfn main() {\n // चैनल बनाएं: tx — भेजने वाला, rx — प्राप्त करने वाला\n let (tx, rx) = mpsc::channel();\n\n // प्रोड्यूसर थ्रेड शुरू करें\n thread::spawn(move || {\n for i in 1..=5 {\n println!("भेज रहे हैं: {}", i);\n tx.send(i).unwrap();\n thread::sleep(Duration::from_millis(500));\n }\n });\n\n // कंज्यूमर थ्रेड (मुख्य थ्रेड)\n for received in rx {\n println!("प्राप्त हुआ: {}", received);\n }\n}\n\n\nइस उदाहरण में, tx (transmitter) को कई प्रोड्यूसर के लिए क्लोन किया जा सकता है, और rx (receiver) एकमात्र कंज्यूमर है। send मेथड Result लौटाता है, जिसे हम unwrap() के माध्यम से हैंडल करते हैं — वास्तविक कोड में एरर को बेहतर तरीके से हैंडल करना चाहिए।
एकाधिक प्रोड्यूसर
\n\nकई प्रोड्यूसर थ्रेड बनाने के लिए, भेजने वाले को क्लोन करें:
\n\nuse std::sync::mpsc;\nuse std::thread;\n\nfn main() {\n let (tx, rx) = mpsc::channel();\n let tx1 = tx.clone();\n\n thread::spawn(move || {\n for i in 1..=3 {\n tx1.send(format!("थ्रेड 1: संदेश {}", i)).unwrap();\n }\n });\n\n thread::spawn(move || {\n for i in 1..=3 {\n tx.send(format!("थ्रेड 2: संदेश {}", i)).unwrap();\n }\n });\n\n for received in rx {\n println!("{}", received);\n }\n}\n\n\nध्यान दें: मूल tx दूसरे थ्रेड में स्थानांतरित हो जाता है, इसलिए हम इसे स्थानांतरित करने से पहले क्लोन करते हैं।
उन्नत तकनीकें: कार्य प्रकार और एरर हैंडलिंग
\n\nवास्तविक एप्लिकेशन में, कार्य शायद ही कभी सरल संख्याएं होते हैं। अक्सर ये स्ट्रक्चर होते हैं जिनमें डेटा और लॉजिक होता है। आइए देखें कि विभिन्न प्रकार के कार्यों के साथ क्यू कैसे व्यवस्थित करें।
\n\nविभिन्न कार्य प्रकारों के लिए एनम
\n\nuse std::sync::mpsc;\nuse std::thread;\n\n#[derive(Debug)]\nenum Task {\n Compute { a: