ضمّ الخيوط وتجميع النتائج
انتظر الخيوط واجمع المخرجات
ضمّ الخيوط وتجميع النتائج درس مجاني في Learn Rust Coding على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Learn Rust Coding، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Learn Rust Coding 4 دروس في المجموع.
لماذا نضم الخيوط؟
يبدأ إنشاء الخيط العمل، لكنكم تحتاجون عادةً إلى نتيجته أو على الأقل إلى دليل على اكتماله. ويُعد الضم طريقة الانتظار لذلك.
ستجمعون في هذا الدرس المقابض، وتضمون الخيوط، وتجمعون القيم التي تنتجها في إجابة نهائية.
يعيد join قيمة Result
يعيد join قيمة من النوع Result. وعند النجاح، تحتوي القيمة المعادة من الإغلاق؛ أما عند حدوث panic في الخيط، فتحتوي على Err.
يمنحكم استدعاء unwrap القيمة مباشرةً، لكنه ينقل panic إذا فشل الخيط.
use std::thread;
fn main() {
let h = thread::spawn(|| 7 * 6);
let value: i32 = h.join().unwrap();
println!("answer = {}", value);
}جمع المقابض أولًا
لتشغيل الخيوط بالتوازي، أنشئوها جميعًا قبل ضم أي منها. وأضيفوا كل مقبض إلى متجه أثناء التقدم.
إذا ضممتم الخيط داخل حلقة الإنشاء، فسوف ينتهي كل خيط قبل بدء التالي، وستفقدون التزامن.
use std::thread;
fn main() {
let handles: Vec<_> = (0..4)
.map(|i| thread::spawn(move || i * i))
.collect();
for h in handles {
println!("{}", h.join().unwrap());
}
}جمع النتائج في Vec
يمكنكم ضم كل مقبض وإضافة القيم المُعادة إلى متجه نتائج.
يسير كل من ترتيب الإنشاء وترتيب الضم من الصفر إلى ثلاثة هنا، ولذلك ينتهي متجه النتائج بترتيب يمكن التنبؤ به.
use std::thread;
fn main() {
let handles: Vec<_> = (1..=4)
.map(|n| thread::spawn(move || n * 10))
.collect();
let results: Vec<i32> = handles
.into_iter()
.map(|h| h.join().unwrap())
.collect();
println!("{:?}", results);
}جمع النتائج المتوازية
بعد جمع النتائج، يمكنكم اختزالها. يحسب كل خيط هنا قيمة جزئية، ثم يجمعها main.
يُعد هذا النمط، الذي يجمع بين map ثم reduce، نمطًا شائعًا في البرمجة المتوازية.
use std::thread;
fn main() {
let handles: Vec<_> = (1..=5)
.map(|n| thread::spawn(move || n * n))
.collect();
let total: i32 = handles
.into_iter()
.map(|h| h.join().unwrap())
.sum();
println!("total = {}", total);
}تقسيم العمل إلى أجزاء
بالنسبة إلى البيانات الأكبر، قسّموها إلى أجزاء وامنحوا كل جزء لخيط خاص به. ويعيد كل خيط مجموعًا جزئيًا.
يتيح استنساخ كل جزء داخل Vec مملوك للخيط امتلاك شريحته بأمان.
use std::thread;
fn main() {
let data: Vec<i32> = (1..=10).collect();
let handles: Vec<_> = data
.chunks(5)
.map(|c| { let c = c.to_vec(); thread::spawn(move || c.iter().sum::<i32>()) })
.collect();
let total: i32 = handles.into_iter().map(|h| h.join().unwrap()).sum();
println!("{}", total);
}معالجة panic في خيط
إذا كان من المحتمل أن تحدث panic في عامل، فلا تستخدموا unwrap دون تفكير. استخدموا المطابقة على Result الناتجة عن join لمعالجة مسار الخطأ.
يحافظ ذلك على استمرار الخيط الرئيسي حتى عند فشل أحد العوامل.
use std::thread;
fn main() {
let h = thread::spawn(|| {
if true { panic!("failed"); }
1
});
match h.join() {
Ok(v) => println!("got {}", v),
Err(_) => println!("thread panicked"),
}
}جمع النتائج في Vec مشترك
بدلًا من إرجاع القيم، يمكن للخيوط الإضافة إلى Arc<Mutex<Vec>> مشترك. وعندها يصبح الترتيب غير حتمي.
بعد ضم جميع الخيوط، اقفلوا المتجه مرة واحدة لقراءة كل نتيجة جُمعت.
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
let out = Arc::new(Mutex::new(vec![]));
let mut handles = vec![];
for i in 0..3 {
let o = Arc::clone(&out);
handles.push(thread::spawn(move || o.lock().unwrap().push(i)));
}
for h in handles { h.join().unwrap(); }
println!("{:?}", out.lock().unwrap());
}الخيوط ذات النطاق
يتيح thread::scope للخيوط استعارة البيانات المحلية من دون move أو Arc. ويضمن النطاق انتهاء جميع الخيوط قبل عودته.
يجعل ذلك القراءة المتوازية لبيانات المكدس سهلة وآمنة.
use std::thread;
fn main() {
let data = vec![1, 2, 3];
thread::scope(|s| {
s.spawn(|| println!("sum {}", data.iter().sum::<i32>()));
s.spawn(|| println!("len {}", data.len()));
});
}إرجاع النتائج من النطاق
تعيد الخيوط ذات النطاق القيم أيضًا من خلال مقابضها. وتضمونها داخل النطاق لجمع النتائج.
وبما أن النطاق يحظر التنفيذ حتى الاكتمال، تظل البيانات المستعارة صالحة طوال الوقت.
use std::thread;
fn main() {
let nums = vec![4, 5, 6];
let total = thread::scope(|s| {
let h = s.spawn(|| nums.iter().sum::<i32>());
h.join().unwrap()
});
println!("total = {}", total);
}لا تنسوا ضم الخيوط
إذا أسقطتم JoinHandle من دون ضمه، يصبح الخيط منفصلًا. ويستمر في العمل، لكنكم تفقدون نتيجته وأي وسيلة لانتظاره.
قد تنتهي العملية أيضًا قبل انتهاء الخيط المنفصل. اضمموا الخيط عندما تحتاجون إلى النتيجة أو إلى التأكد من الاكتمال.
تحقق سريع
اختبر مدى فهمكم لضمّ النتائج وتجميعها.
مراجعة
تعلّمتم أن join يعيد Result يحمل قيمة الخيط أو حالة الذعر الخاصة به. أنشئوا جميع الخيوط أولًا، ثم استخدموا join للحفاظ على التزامن.
يمكنكم تجميع النتائج في Vec، أو اختزالها، أو دفعها إلى Arc<Mutex<Vec>> مشترك. تستعير الخيوط ذات النطاق البيانات المحلية بأمان، وإسقاط المقبض يفصل الخيط.
أصبح لديكم الآن الأدوات الأساسية للتعامل مع الخيوط والحالة المشتركة في Rust.
الأسئلة الشائعة
هل درس «ضمّ الخيوط وتجميع النتائج» مجاني؟
نعم — نص درس «ضمّ الخيوط وتجميع النتائج» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Learn Rust Coding، انتقل إلى CoddyKit PRO. تتضمن دورة Learn Rust Coding 4 دروس في المجموع.
ماذا ستتعلم في «ضمّ الخيوط وتجميع النتائج»؟
انتظر الخيوط واجمع المخرجات تتمرن على Learn Rust Coding مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Learn Rust Coding؟
لا تُشترط خبرة سابقة. Learn Rust Coding على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.
كم من الوقت يستغرق درس «ضمّ الخيوط وتجميع النتائج»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Learn Rust Coding هذا؟
نعم. كل درس في Learn Rust Coding يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- إنشاء الخيوط
- نقل البيانات إلى الخيوط
- المشاركة باستخدام Arc وMutex
- ضمّ الخيوط وتجميع النتائج