المشاكل التي يحلها تعدد العمليات في Java
في الأساس، تم اختراع Java multithreading لحل مشكلتين رئيسيتين:-
تنفيذ إجراءات متعددة في نفس الوقت.
في المثال أعلاه، قامت خيوط مختلفة (أي أفراد الأسرة) بتنفيذ عدة إجراءات بالتوازي: غسل الأطباق، والذهاب إلى المتجر، وطي الأشياء.
يمكن إعطاء مثال أكثر "مبرمج". تخيل أن لديك برنامجًا بواجهة مستخدم. عند الضغط على زر متابعة، يجب أن تتم بعض العمليات الحسابية داخل البرنامج، ويجب أن يرى المستخدم شاشة الواجهة التالية. إذا تم تنفيذ هذه الإجراءات بالتتابع، بعد النقر فوق الزر "متابعة"، فسيتم تجميد البرنامج ببساطة. وسيظهر للمستخدم نفس الشاشة مع زر "متابعة" حتى تتم جميع الحسابات الداخلية ويصل البرنامج إلى الجزء الذي سيبدأ فيه رسم الواجهة.
حسنا، دعونا ننتظر بضع دقائق!
يمكننا أيضًا إعادة صياغة برنامجنا، أو، كما يقول المبرمجون، "الموازاة". اسمح بإجراء الحسابات اللازمة في موضوع واحد، وعرض الواجهة في موضوع آخر. معظم أجهزة الكمبيوتر لديها موارد كافية لهذا الغرض. وفي هذه الحالة لن يكون البرنامج “غبيا”، وسيتنقل المستخدم بهدوء بين شاشات الواجهة دون القلق بشأن ما يحدث بداخله. لا يتدخل :)
-
تسريع العمليات الحسابية.
كل شيء أبسط بكثير هنا. إذا كان معالجنا يحتوي على عدة مراكز، وكانت معظم المعالجات الآن متعددة النواة، فيمكن حل قائمة المهام لدينا بالتوازي بواسطة عدة مراكز. من الواضح أننا إذا أردنا حل 1000 مشكلة وتم حل كل واحدة منها في ثانية واحدة، فسوف تتعامل نواة واحدة مع القائمة في 1000 ثانية، ونواتان في 500 ثانية، وثلاثة في ما يزيد قليلاً عن 333 ثانية، وهكذا.
Thread
. أي أنه لإنشاء 10 سلاسل وتشغيلها، ستحتاج إلى 10 كائنات من هذه الفئة. لنكتب أبسط مثال:
public class MyFirstThread extends Thread {
@Override
public void run() {
System.out.println("I'm Thread! My name is " + getName());
}
}
لإنشاء سلاسل رسائل وتشغيلها، نحتاج إلى إنشاء فئة ووراثتها من ملف java.lang
. Thread
وتجاوز الطريقة فيه run()
. هذا الأخير مهم جدا. في الطريقة التي run()
نصف بها المنطق الذي يجب أن ينفذه مؤشر الترابط الخاص بنا. الآن، إذا أنشأنا مثيلًا MyFirstThread
وقمنا بتشغيله، run()
فستطبع الطريقة سطرًا باسمها على وحدة التحكم: getName()
تطبع الطريقة اسم "النظام" للخيط، والذي يتم تعيينه تلقائيًا. على الرغم من أنه في الواقع لماذا "إذا"؟ دعونا ننشئ ونختبر!
public class Main {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
MyFirstThread thread = new MyFirstThread();
thread.start();
}
}
}
إخراج وحدة التحكم: أنا خيط! اسمي الموضوع-2 أنا الموضوع! اسمي الموضوع-1 أنا الموضوع! اسمي الموضوع-0 أنا الموضوع! اسمي الموضوع-3 أنا الموضوع! اسمي الموضوع-6 أنا الموضوع! اسمي الموضوع-7 أنا الموضوع! اسمي Thread-4 أنا خيط! اسمي الموضوع-5 أنا الموضوع! اسمي الموضوع-9 أنا الموضوع! اسمي Thread-8 نقوم بإنشاء 10 سلاسل (كائنات) MyFirstThread
ترث منها Thread
وتشغيلها عن طريق استدعاء طريقة الكائن start()
. بعد استدعاء الطريقة ، start()
تبدأ طريقتها في العمل run()
، ويتم تنفيذ المنطق المكتوب فيها. ملاحظة: أسماء المواضيع ليست بالترتيب. إنه أمر غريب جدًا، لماذا لم يتم إعدامهم بدورهم: Thread-0
, Thread-1
, Thread-2
وهكذا؟ هذا هو بالضبط مثال على الحالات التي لن ينجح فيها التفكير القياسي "المتسلسل". الحقيقة هي أننا في هذه الحالة نصدر فقط أوامر لإنشاء وإطلاق 10 سلاسل رسائل. يتم تحديد الترتيب الذي سيتم إطلاقها به بواسطة برنامج جدولة الخيط: آلية خاصة داخل نظام التشغيل. إن كيفية تنظيمها بالضبط وعلى أي مبدأ تتخذ القرارات هو موضوع معقد للغاية، ولن نتعمق فيه الآن. الشيء الرئيسي الذي يجب تذكره هو أن المبرمج لا يمكنه التحكم في تسلسل تنفيذ الخيط. لإدراك خطورة الموقف، حاول تشغيل الطريقة main()
من المثال أعلاه عدة مرات. إخراج وحدة التحكم الثانية: أنا خيط! اسمي الموضوع-0 أنا الموضوع! اسمي Thread-4 أنا خيط! اسمي الموضوع-3 أنا الموضوع! اسمي الموضوع-2 أنا الموضوع! اسمي الموضوع-1 أنا الموضوع! اسمي الموضوع-5 أنا الموضوع! اسمي الموضوع-6 أنا الموضوع! اسمي Thread-8 أنا خيط! اسمي الموضوع-9 أنا الموضوع! اسمي Thread-7 إخراج وحدة التحكم الثالثة: أنا Thread! اسمي الموضوع-0 أنا الموضوع! اسمي الموضوع-3 أنا الموضوع! اسمي الموضوع-1 أنا الموضوع! اسمي الموضوع-2 أنا الموضوع! اسمي الموضوع-6 أنا الموضوع! اسمي Thread-4 أنا خيط! اسمي الموضوع-9 أنا الموضوع! اسمي الموضوع-5 أنا الموضوع! اسمي الموضوع-7 أنا الموضوع! اسمي الموضوع-8
المشاكل التي يخلقها تعدد العمليات
في مثال الكتب، رأيت أن تعدد مؤشرات الترابط يحل مشكلات مهمة جدًا، كما يؤدي استخدامه إلى تسريع عمل برامجنا. في كثير من الحالات - عدة مرات. ولكن ليس من قبيل الصدفة أن يعتبر تعدد مؤشرات الترابط موضوعًا معقدًا. ففي النهاية، إذا تم استخدامه بشكل غير صحيح، فإنه يخلق مشاكل بدلاً من حلها. عندما أقول "خلق المشاكل"، لا أقصد شيئًا مجردًا. هناك مشكلتان محددتان يمكن أن تسببهما مؤشرات الترابط المتعددة: حالة الجمود وحالة السباق. حالة الجمود هي حالة تنتظر فيها سلاسل رسائل متعددة الموارد التي تشغلها بعضها البعض، ولا يمكن لأي منها الاستمرار في التنفيذ. سنتحدث عنها أكثر في المحاضرات القادمة، ولكن في الوقت الحالي سيكفي هذا المثال: تخيل أن الخيط 1 يعمل مع بعض الكائنات 1، والخيط 2 يعمل مع الكائن 2. البرنامج مكتوب هكذا :- سيتوقف Thread-1 عن العمل مع Object-1 ويتحول إلى Object-2 بمجرد توقف Thread-2 عن العمل مع Object 2 ويتحول إلى Object-1.
- سيتوقف Thread-2 عن العمل مع Object-2 ويتحول إلى Object-1 بمجرد توقف Thread-1 عن العمل مع Object 1 ويتحول إلى Object-2.
public class MyFirstThread extends Thread {
@Override
public void run() {
System.out.println("Выполнен поток " + getName());
}
}
public class Main {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
MyFirstThread thread = new MyFirstThread();
thread.start();
}
}
}
والآن تخيل أن البرنامج هو المسؤول عن تشغيل الروبوت الذي يقوم بتحضير الطعام! الخيط 0 يخرج البيض من الثلاجة. تيار 1 يتحول على الموقد. يقوم Stream-2 بإخراج مقلاة ووضعها على الموقد. تيار 3 يشعل النار على الموقد. تيار 4 يصب الزيت في المقلاة. يكسر التيار 5 البيض ويصبه في المقلاة. يرمي الدفق 6 القذائف في سلة المهملات. يقوم Stream-7 بإزالة البيض المخفوق الجاهز من الحرارة. يضع Potok-8 البيض المخفوق على طبق. Stream-9 يغسل الأطباق. انظر إلى نتائج برنامجنا: تم تنفيذ مؤشر الترابط -0 تم تنفيذ مؤشر الترابط -2 تم تنفيذ مؤشر الترابط -1 تم تنفيذ مؤشر الترابط -4 تم تنفيذ مؤشر الترابط -9 تم تنفيذ مؤشر الترابط -5 تم تنفيذ مؤشر الترابط -8 تم تنفيذ مؤشر الترابط -7 تم تنفيذ مؤشر الترابط -7 تم تنفيذ الخيط -3 تم تنفيذ الخيط -6 هل النص ممتع؟ :) وكل ذلك لأن تشغيل برنامجنا يعتمد على الترتيب الذي يتم به تنفيذ المواضيع. عند أدنى انتهاك للتسلسل، يتحول مطبخنا إلى جحيم، ويدمر الروبوت المجنون كل شيء من حوله. هذه أيضًا مشكلة شائعة في البرمجة متعددة الخيوط، والتي ستسمع عنها أكثر من مرة. وفي نهاية المحاضرة، أود أن أرشح لك كتابًا عن تعدد الخيوط.
GO TO FULL VERSION