0Pricing
Java Academy · درس

إنشاء التدفقات المتوازية

parallel() وparallelStream()

إنشاء التدفقات المتوازية درس مجاني في Java Academy على CoddyKit. هذا هو الدرس 1 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Java Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Java Academy 4 دروس في المجموع.

ما الذي تفعله التدفقات المتوازية

تقسم التدفقات المتوازية بياناتها وتعالج الأجزاء على خيوط تنفيذ متعددة، ثم تجمع النتائج. والهدف هو زيادة معدل المعالجة في أحمال العمل الكبيرة.

import java.util.stream.IntStream;

public class Main {
    public static void main(String[] args) {
        int sum = IntStream.rangeClosed(1, 1000)
            .parallel()
            .sum();
        System.out.println(sum);
    }
}

استخدام parallel() مع تدفق موجود

يحوّل استدعاء parallel() التدفق التسلسلي إلى تدفق متوازٍ. ويمكن أن يظهر هذا الاستدعاء في أي موضع ضمن خط المعالجة.

import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<Integer> nums = List.of(1, 2, 3, 4, 5);
        int total = nums.stream()
            .parallel()
            .mapToInt(Integer::intValue)
            .sum();
        System.out.println(total);
    }
}

استخدام parallelStream() مع المجموعات

ينشئ Collection.parallelStream() تدفقًا متوازيًا مباشرةً، وهو اختصار لاستخدام stream().parallel().

import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<String> words = List.of("a", "bb", "ccc");
        int chars = words.parallelStream()
            .mapToInt(String::length)
            .sum();
        System.out.println(chars);
    }
}

العودة إلى التنفيذ التسلسلي

يعيد sequential() التدفق إلى التنفيذ باستخدام خيط واحد. ويكون الاستدعاء الأخير لـparallel() أو sequential() هو المؤثر في خط المعالجة بأكمله.

import java.util.stream.IntStream;

public class Main {
    public static void main(String[] args) {
        int sum = IntStream.rangeClosed(1, 100)
            .parallel()
            .sequential()
            .sum();
        System.out.println(sum);
    }
}

التحقق باستخدام isParallel

يُبلغ isParallel() عمّا إذا كان التدفق سيُنفَّذ بشكل متوازٍ.

import java.util.stream.IntStream;

public class Main {
    public static void main(String[] args) {
        System.out.println(IntStream.range(0, 10).isParallel());
        System.out.println(IntStream.range(0, 10).parallel().isParallel());
    }
}

النتيجة نفسها، والتنفيذ مختلف

بالنسبة إلى العمليات التجميعية مثل الجمع، تعيد التدفقات المتوازية والتسلسلية النتيجة نفسها. ويختلف أسلوب التنفيذ فقط.

import java.util.stream.IntStream;

public class Main {
    public static void main(String[] args) {
        int seq = IntStream.rangeClosed(1, 50).sum();
        int par = IntStream.rangeClosed(1, 50).parallel().sum();
        System.out.println(seq == par);
    }
}

مجموعة ForkJoinPool المشتركة

تستخدم التدفقات المتوازية ForkJoinPool.commonPool() المشتركة. ويبلغ حجمها الافتراضي عدد المعالجات المتاحة ناقصًا واحدًا.

public class Main {
    public static void main(String[] args) {
        System.out.println(Runtime.getRuntime().availableProcessors());
    }
}

ترتيب الخيوط غير مضمون

عند استخدام forEach، قد تطبع التدفقات المتوازية العناصر بأي ترتيب، لأن الأجزاء تنتهي في أوقات مختلفة. استخدم forEachOrdered إذا كان الترتيب مهمًا.

import java.util.stream.IntStream;

public class Main {
    public static void main(String[] args) {
        IntStream.rangeClosed(1, 5)
            .parallel()
            .forEachOrdered(System.out::println);
    }
}

يجمّع الاختزال النتائج الجزئية

يحسب الاختزال المتوازي داخليًا نتائج جزئية لكل جزء، ثم يدمجها باستخدام دالة الدمج. ويجب أن تكون العملية تجميعية لضمان صحة النتائج.

import java.util.stream.IntStream;

public class Main {
    public static void main(String[] args) {
        int product = IntStream.rangeClosed(1, 6)
            .parallel()
            .reduce(1, (a, b) -> a * b);
        System.out.println(product);
    }
}

التجميع بشكل متوازٍ

يدعم إطار عمل أدوات التجميع التجميعَ المتوازي من خلال دمج الحاويات الجزئية. ويعمل groupingBy بشكل صحيح في التنفيذ المتوازي.

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List<String> words = List.of("apple", "banana", "avocado", "cherry");
        Map<Character, List<String>> byFirst = words.parallelStream()
            .collect(Collectors.groupingBy(w -> w.charAt(0)));
        System.out.println(byFirst);
    }
}

لا تصبح كل التدفقات أسرع

إن تفعيل التوازي أمر بسيط، لكنه لا يكون مفيدًا دائمًا. فقد تكون مجموعات البيانات الصغيرة أو العمليات قليلة التكلفة أبطأ عند تنفيذها بشكل متوازٍ بسبب تكلفة التقسيم والدمج.

import java.util.stream.IntStream;

public class Main {
    public static void main(String[] args) {
        long count = IntStream.rangeClosed(1, 10)
            .parallel()
            .filter(n -> n % 2 == 0)
            .count();
        System.out.println(count);
    }
}

تحقق سريع

أي مجموعة خيوط تنفّذ التدفقات المتوازية افتراضيًا؟

مراجعة

لقد أنشأت تدفقات متوازية:

  • parallel() يحوّل أي تدفق إلى متوازٍ، بينما parallelStream() اختصار خاص بالمجموعات.
  • يعيد sequential() التدفق إلى التنفيذ التسلسلي، ويكون الاستدعاء الأخير هو المؤثر.
  • تُنفَّذ على ForkJoinPool.commonPool() المشتركة.
  • تتطابق النتائج مع التنفيذ التسلسلي في العمليات التجميعية، لكن الترتيب والسرعة غير مضمونين.

الأسئلة الشائعة

هل درس «إنشاء التدفقات المتوازية» مجاني؟

نعم — نص درس «إنشاء التدفقات المتوازية» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Java Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Java Academy 4 دروس في المجموع.

ماذا ستتعلم في «إنشاء التدفقات المتوازية»؟

parallel() وparallelStream() تتمرن على Java Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Java Academy؟

لا تُشترط خبرة سابقة. Java Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 4.

كم من الوقت يستغرق درس «إنشاء التدفقات المتوازية»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Java Academy هذا؟

نعم. كل درس في Java Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. إنشاء التدفقات المتوازية
  2. متى تفيد المعالجة المتوازية
  3. سلامة الخيوط والآثار الجانبية
  4. الأخطاء الشائعة
← العودة إلى Java Academy