Javaالإنترفيس Runnable في جافا
- مقدمة
- دوال الإنترفيس Runnable
- أمثلة شاملة
- أهمية الإنترفيس Runnable في التطبيقات الفعلية
مقدمة
المشكلة الوحيدة التي قد تواجهها عند إنشاء الـ Thread من خلال وراثة الكلاس Thread هي أن الكلاس يصبح غير قادر على أن يرث من كلاس آخر, لأنه لا يمكن للكلاس أن يفعل extends لأكثر من كلاس.
لحل مشكلة تعدد الوراثة, يمكنك جعل الكلاس يطبق الإنترفيس Runnable و بداخله نقوم بإنشاء كائن من الكلاس Thread و نربط به.
بناؤه
خطوات تطبيق الإنترفيس Runnable
الكلاس الذي يطبق الإنترفيس Runnable عليه القيام بالخطوات التالية:
- تطبيق الإنترفيس Runnable, أي أن يفعل له implements.
- كتابة محتوى الدالة run(), أي أن يفعل لها Override و يضع فيها جميع الأوامر التي يريدها أن تتنفذ عند تشغيل كائن الـ Thread.
مثال
خطوات إنشاء كائن من الكلاس Thread و ربطه بالكلاس الذي يطبق الإنترفيس Runnable
لإنشاء كائن من الكلاس الذي يطبق الإنترفيس Runnable و تنفيذ أوامره بشكل متوازي مع باقي الأوامر الموجودة في البرنامج, عليك إتباع الخطوات التالية:
- إنشاء كائن من الكلاس الذي يرث من الإنترفيس Runnable.
- إنشاء كائن من الكلاس Thread, و تمرير كائن من الكلاس الذي يطبق الإنترفيس Runnable كـ Argument له.
- إستدعاء الدالة start() لتشغيله.
- بعدها يمكنك التعامل معه كـ Thread عادي و التحكم بطريقة تنفيذ أوامره كما تشاء.
مثال
دوال الإنترفيس Runnable
الإنترفيس Runnable يملك الدالة التالية فقط.
الكلاس الذي يطبق الإنترفيس Runnable يجب أن يفعل لها Override, و يضع بداخلها الأوامر التي يريدها أن تتنفذ عند تشغيل كائن الـ Thread.
لتنفيذ أوامر الدالة run() بشكل متوازي مع باقي الأوامر الموجودة في البرنامج, عليك إستدعاء الدالة start() من كائن الـ Thread المرتبط بالكلاس الذي يطبق الإنترفيس Runnable, و الذي يملك الدالة run().
تذكر: إستدعاء الدالة run() بشكل مباشر لا يجعلها تعمل بشكل متوازي مع البرنامج.
أمثلة شاملة
هذه نفس الأمثلة التي وضعناها في شرح الكلاس Thread من حيث الأفكار, مع بعض التعديلات لجعل الكلاس يطبق الإنترفيس Runnable بدل أن يرث من الكلاس Thread.
المثال الأول
في المثال التالي قمنا بإنشاء برنامج يعرض الوقت الحالي طالما أن البرنامج شغال.
في البداية قمنا بإنشاء كلاس إسمه RealTime يطبق الإنترفيس Runnable.
بعدها فعلنا Override للدالة run() لجعلها تطبع الوقت الحالي.
ثم قمنا بإنشاء كلاس إسمه Main لتجربة هذا الـ Thread.
في الكلاس Main قمنا بإنشاء كائن من الكلاس Thread ربطناه بالكلاس RealTime, ثم قمنا بتشغيله بواسطة الدالة start().
إذاً عند تشغيل هذا البرنامج سيتم عرض الوقت الحالي طالما أن البرنامج شغال.
عند تشغيل البرنامج, سيتم عرض الوقت الحالي كل ثانية كالتالي.
المثال الثاني
المثال التالي عبارة عن برنامج يقوم بإختبار قدرة المستخدم في العمليات الحسابية, فهو يقوم بخلق عمليات جمع عشوائية خلال مدة معينة, و إنتظار المستخدم للإجابة عليها, و في الأخير سيتم عرض النتيجة النهائية له.
في المثال التالي قمنا بإنشاء كلاس إسمه ExamTimer يطبق الإنترفيس Runnable.
بعدها فعلنا Override للدالة run() حتى نجعل أي كائن من الكلاس ExamTimer ينتظر مدة 20 ثانية بعد تشغيله, ثم يتوقف مباشرةً عن العمل.
ثم قمنا بإنشاء كلاس إسمه Main, و الذي سيستخدم الكلاس ExamTimer كمؤقت.
في الكلاس Main فعلنا الأشياء التالية:
- أنشأنا كائن من الكلاس ExamTimer إسمه et.
- أنشأنا كائن من الكلاس Thread إسمه t و ربطناه بالكائن et.
- قمنا بتشغيل الكائن t بواسطة الدالة start().
- قمنا بتعريف المتغيرات num1 و num2 لتخزين الأرقام العشوائية التي سيتم توليدها في البرنامج.
- قمنا بتعريف المتغير userAnswer لتخزين العدد الذي سيدخله المستخدم في كل مرة.
- قمنا بتعريف المتغيرات operationsCounter, correctAnswersCounter و wrongAnswersCounter كعدادات في البرنامج.
operationsCounter: لتخزين عدد العمليات التي تظهر أمام المستخدم.
correctAnswersCounter: لتخزين عدد إجابات المستخدم الصحيحة.
wrongAnswersCounter: لتخزين عدد إجابات المستخدم الخاطئة. - قمنا بتعريف حلقة while تستمر في توليد أرقام العشوائية, إعداد عمليات جمع و إنتظار المستخدم لمعرفة الإجابة إلخ.. بالإعتماد على الدالة isAlive() التي تبقي الحلقة تعيد تنفيذ الأوامر الموجودة فيها طالما أن مدة الإنتظار المحددة للكائن t غير منتهية بعد.
عند تشغيل البرنامج, سنحصل على نتيجة تشبه النتيجة التالية عند التشغيل.
الأرقام التي قمنا بتعليمها باللون الأصفر هي التي قمنا بإدخالها عند تجربة البرنامج.
0 + 8 = 8
5 + 7 = 11
8 + 8 = 16
6 + 6 = 12
3 + 9 = 12
7 + 4 = 14
9 + 4 = 13
Time end..
--------- Result --------
Number of operations: 7
Number of correct answers: 5
Number of wrong answers: 2
المثال الثالث
في المثال التالي قمنا تشغيل أكثر من كائن Runnable في وقت واحد. الهدف هنا جعلك تدرك أن الأوامر لا تتنفذ فعلياً في وقت واحد لكنها تتنفذ بسرعة عالية جداً تجعل المستخدم يظن أنها تحدث في وقت واحد.
في البداية قمنا بإنشاء كلاس إسمه MyRunnable يطبق الإنترفيس Runnable.
بعدها فعلنا Override للدالة run() حتى نجعل أي كائن من الكلاس MyRunnable يطبع إسمه كل ثانية.
ثم قمنا بإنشاء كلاس إسمه Main, و الذي قمنا فيه بإنشاء ثلاث كائنات من الكلاس MyRunnable, و ربطهم بثلاث كائنات من الكلاس Thread و تشغيلهم مع بعض.
عند تشغيل البرنامج, نلاحظ أنه يطبع ثلاثة أسطر كل ثانية .
المثال الرابع
في المثال التالي قمنا بإنشاء برنامج يظهر أمام المستخدم لائحة فيها أربع خيارات: تشغيل صوت التنبيه, إيقافه, إعادته للعمل, إيقافه نهائياً.
ميزة هذا البرنامج أنه يمكن تشغيل الإنذار أو إيقافه في نفس الوقت الذي يطلب فيه من المستخدم إدخال رقم الخيار.
في البداية قمنا بإنشاء برنامج يظهر أمام المستخدم لائحة فيها أربع خيارات: تشغيل إنذار, إيقافه, إعادته للعمل, إيقافه نهائياً.
ميزة هذا البرنامج يمكنه تشغيل الإنذار في نفس الوقت الذي يطلب فيه من المستخدم إدخال رقم الخيار.
في البداية قمنا بإنشاء كلاس إسمه Alert يطبق الإنترفيس Runnable.
بعدها فعلنا Override للدالة run() حتى نجعل أي كائن من الكلاس Alert يصدر صوت تنبيه عند تشغيله.
ثم قمنا بإنشاء كلاس إسمه Main لتجربة الكلاس Alert.
عند تشغيل البرنامج ظهر لك أربع خيارات: تشغيل صوت التنبيه, إيقافه, إعادته للعمل, إيقافه نهائياً.
ستلاحظ أن البرنامج قادر على تشغيل صوت التنبيه في نفس الوقت الذي يطلب فيه من المستخدم إدخال رقم الخيار.
إنتبه: إرفع صوت الحاسوب إلا أعلا مستوى حتى تسمع صوت التنبيه عند تشغيله.
قم بتشغيل البرنامج و أدخل نفس القيم التي قمنا بتعليمها باللون الأصفر لتلاحظ كيف يعمل.
لا تنسى رفع صوت حاسوبك إلى أعلا مستوى حتى تسمع صوت التنبيه و هو يعمل.
| Enter (1) to Start |
| Enter (2) to Pause |
| Enter (3) to Resume |
| Enter (4) to Stop |
-----------------------
User input >> 1
User input >> 2
User input >> 3
User input >> 2
User input >> 3
User input >> 4
أهمية الإنترفيس Runnable في التطبيقات الفعلية
أهم نقطة في تطبيق الإنترفيس Runnable هي أنه يجعلك قادراً على بناء كلاس يعمل كـ Thread و بنفس الوقت يرث من كلاس آخر.
مثال
هذا الأسلوب مهم جداً و قد تحتاجه عند بناء تطبيق فيه واجهة مستخدم (GUI) و يعمل بشكل متوازي مع باقي الأوامر الموجودة في البرنامج.
لأنه عند بناء تطبيق فيه GUI عليك أن تفعل extends من كلاس محدد مثل الكلاس JFrame, و تفعل implements للإنترفيس Runnable.
كمثال بسيط, هذا الأسلوب يجعلك قادراً على بناء تطبيق فيه واجهة مستخدم و يعرض لك الوقت و التاريخ.
لا تقلق ستتعلم هذه الأمور في دروس لاحقة.