0Pricing
Java Academy · درس

معالجة الأخطاء والإلغاء

تمرير حالات الفشل بسلاسة

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

حالات الفشل في شجرة المهام

عند تشغيل المهام الفرعية بالتزامن، يمكن أن تحدث الأخطاء في أي فرع. ويوفّر التزامن المُنظَّم طريقة منضبطة لنشر هذه الإخفاقات إلى المهمة الأب.

يتناول هذا الدرس الاستثناءات والإلغاء والمقاطعة والمهل الزمنية.

مواضع ظهور الاستثناءات

لا يؤدي طرح مهمة فرعية لاستثناء إلى انهيار البرنامج فورًا. إذ يُلتقط الاستثناء في مقبض Subtask الخاص بها. ويعتمد موضع ظهوره على السياسة:

  • ShutdownOnFailure: عند throwIfFailed()
  • ShutdownOnSuccess: عند result() إذا لم تنجح أي مهمة

نشر الأخطاء باستخدام throwIfFailed

تفشل هنا إحدى المهام الفرعية. ويعيد throwIfFailed() طرحها بعد تغليفها في ExecutionException، ثم نلتقطها في main.

import java.util.concurrent.*;

public class Main {
    public static void main(String[] args) throws InterruptedException {
        try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
            scope.fork(() -> "ok");
            scope.fork(() -> { throw new RuntimeException("boom"); });
            scope.join();
            scope.throwIfFailed();
            System.out.println("never reached");
        } catch (ExecutionException e) {
            System.out.println("Caught cause: " + e.getCause().getMessage());
        }
    }
}

التحويل إلى استثناء مخصص

يقبل throwIfFailed دالةً لتغليف السبب في نوع الاستثناء الخاص بك، مما يحافظ على نظافة واجهة برمجة التطبيقات.

import java.util.concurrent.StructuredTaskScope;

class DataAccessException extends Exception {
    DataAccessException(Throwable cause) { super(cause); }
}

public class Main {
    public static void main(String[] args) throws Exception {
        try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
            scope.fork(() -> { throw new RuntimeException("db down"); });
            scope.join();
            scope.throwIfFailed(DataAccessException::new);
        } catch (DataAccessException e) {
            System.out.println("Wrapped: " + e.getCause().getMessage());
        }
    }
}

الإلغاء التلقائي

عندما تفشل إحدى المهام الفرعية ضمن ShutdownOnFailure، يلغي النطاق المهام الشقيقة بمقاطعة خيوطها. ولا تحتاج إلى كتابة أي شيفرة للإلغاء بنفسك.

يمنع ذلك هدر العمل وبقاء المهام معلّقة.

المقاطعة هي الآلية

يعمل الإلغاء عبر مقاطعة الخيط الافتراضي للمهمة الفرعية. وينبغي للشيفرة التعاونية أن:

  • تسمح للاستدعاءات الحاجزة بطرح InterruptedException
  • تتحقق دوريًا من Thread.currentThread().isInterrupted() داخل الحلقات الطويلة

الاستجابة للمقاطعة

تتحقق هذه المهمة من علامة المقاطعة داخل حلقة، حتى تتمكن من التوقف مبكرًا عند إيقاف النطاق.

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Thread t = Thread.ofVirtual().start(() -> {
            long count = 0;
            while (!Thread.currentThread().isInterrupted()) {
                count++;
                if (count == 1_000_000) break;
            }
            System.out.println("Stopped after " + count + " iterations");
        });
        t.join();
    }
}

المواعيد النهائية مع joinUntil

لتحديد إجمالي الوقت، استخدم joinUntil(Instant). فإذا انقضى الموعد النهائي قبل اكتمال جميع المهام الفرعية، فسيُطرح TimeoutException ويوقف النطاق بقية المهام.

شكل نموذجي مع مهلة

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

import java.time.*;
import java.util.concurrent.*;

public class Main {
    public static void main(String[] args) throws InterruptedException {
        try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
            scope.fork(() -> "fast");
            scope.joinUntil(Instant.now().plus(Duration.ofSeconds(2)));
            scope.throwIfFailed();
            System.out.println("Completed within deadline");
        } catch (TimeoutException e) {
            System.out.println("Deadline exceeded");
        } catch (ExecutionException e) {
            System.out.println("A subtask failed");
        }
    }
}

أعِد التحقق دائمًا بعد join

القاعدة هي: بعد join() أو joinUntil، استدعِ دائمًا throwIfFailed() أو اقرأ result() قبل الوثوق بقيمة أي مهمة فرعية. قد يؤدي تخطي ذلك إلى إخفاء حالات الفشل.

ضمان الإيقاف النظيف

بغض النظر عن كيفية انتهاء النطاق، سواء بصورة طبيعية أو بسبب فشل أو مهلة زمنية، يضمن إغلاق كتلة try-with-resources انتهاء كل خيط من خيوط المهام الفرعية. لا توجد تسرّبات ولا مهام يتيمة.

تحقق سريع

تذكّر كيفية إيقاف المهام الفرعية الشقيقة.

مراجعة

تعلّمت معالجة الأخطاء والإلغاء:

  • تظهر الاستثناءات عند throwIfFailed() أو result()
  • حوّل الأسباب إلى استثناءات مخصصة عبر throwIfFailed(mapper)
  • يعمل الإلغاء من خلال مقاطعة الخيط؛ لذا اكتب مهام تعاونية
  • يفرض joinUntil موعدًا نهائيًا للمجموعة
  • يضمن إغلاق النطاق التنظيف دائمًا

وبذلك يكتمل مقرر التزامن المُنظَّم.

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

هل درس «معالجة الأخطاء والإلغاء» مجاني؟

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

ماذا ستتعلم في «معالجة الأخطاء والإلغاء»؟

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

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

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

كم من الوقت يستغرق درس «معالجة الأخطاء والإلغاء»؟

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

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

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

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

  1. نموذج التزامن المنظّم
  2. StructuredTaskScope
  3. الإيقاف عند الفشل والنجاح
  4. معالجة الأخطاء والإلغاء
← العودة إلى Java Academy