انتقل مباشرة إلى هذه النقطة
في دوائر تكنولوجيا المعلومات، عندما نتحدث عن التزامن، لا بد أن نتحدث عن سلسلة من الخيوط التي تعمل في وقت واحد على جهاز الكمبيوتر. إذا كان هناك معالجات متعددة أو معالج متعدد النواة على هذا الكمبيوتر، فهو في الواقع "يعمل في وقت واحد"؛ ومع ذلك، إذا كان الكمبيوتر يحتوي على معالج أحادي النواة فقط، فإن "التشغيل المتزامن" هو مجرد مظهر.
تدعم جميع أنظمة التشغيل الحديثة التنفيذ المتزامن للمهام. يمكنك الاستماع إلى الموسيقى وقراءة الأخبار عبر الإنترنت دون تأخير البريد الإلكتروني الأول. يمكننا القول أن هذا التزامن هو التزامن على مستوى العملية. داخل العملية، أستطيع أيضًا أن أرى أن هناك العديد من المهام المتزامنة. نحن نسمي المهام المتزامنة التي تعمل في سلاسل العمليات.
المفهوم الشائع الآخر المتعلق بالتزامن هو التوازي. هناك بعض الاختلافات وبعض الروابط بين التزامن والتوازي. يعتقد بعض المبرمجين (المؤلف، الذي يُترجم حرفيًا باسم "المبرمج") أن تنفيذ تطبيق باستخدام سلاسل رسائل متعددة على معالج أحادي النواة هو عملية متزامنة، ويمكنك ملاحظة تنفيذ المبرمج، بالإضافة إلى ذلك، عندما يعمل برنامجك بسلاسل رسائل متعددة، عند تشغيل سلاسل الرسائل في المعالجات المتعددة أو المعالجات متعددة النواة، تكون متوازية. هناك أيضًا بعض المبرمجين الذين يعتقدون أنه إذا لم يتم تنفيذ سلاسل عمليات التطبيق بترتيب محدد مسبقًا، فهذا يعني التزامن؛ ومن أجل تبسيط حل المشكلة، يتم استخدام سلاسل المحادثات، ويتم تنفيذ هذه الخيوط بترتيب معين هذا هو التوازي.
سيستخدم هذا الفصل اثني عشر مثالًا لتوضيح كيفية استخدام Java7 API لتنفيذ بعض عمليات سلسلة المحادثات الأساسية. ستتمكن من رؤية، في برنامج Java، كيفية إنشاء وتنفيذ سلاسل الرسائل، وكيفية التحكم في تنفيذ سلاسل الرسائل، وكيفية التعامل مع مجموعة من سلاسل الرسائل كوحدة، وما إلى ذلك.
في هذا القسم سوف نتعلم كيفية إنشاء موضوع في برنامج جافا وكيفية تشغيله. في برنامج Java، كل شيء عبارة عن كائن، وكذلك الخيوط. هناك طريقتان لإنشاء المواضيع:
1. وراثة فئة الموضوع وتجاوز طريقة التشغيل () ؛
2. قم بإنشاء فئة تنفذ واجهة Runnable، ثم قم بإنشاء كائن من فئة Thread، ثم قم بتمرير مثيل الفئة التي تنفذ واجهة Runnable كمعلمة إلى مثيل فئة Thread.
في هذا القسم سنستخدم الطريقة الثانية لإنشاء عشرة مواضيع وتشغيلها. يقوم كل خيط بحساب وطباعة منتج عددين صحيحين خلال عشرة.
تعرف عليه
اتبع الخطوات الموضحة أدناه لتنفيذ هذا المثال:
1. قم بإنشاء فئة باسم الحاسبة وقم بتنفيذ الواجهة القابلة للتشغيل. الرمز هو كما يلي:
انسخ رمز الكود كما يلي:
تطبق حاسبة الفئة العامة Runnable {
2. قم بتعريف سمة عدد صحيح خاصة تسمى الرقم، وقم بتنفيذ مُنشئ هذه الفئة لتهيئة السمة التي تم الإعلان عنها للتو. الرمز هو كما يلي:
انسخ رمز الكود كما يلي:
رقم خاص؛
الحاسبة العامة (رقم int) {
this.number = number;
}
3. تنفيذ طريقة التشغيل () وهي البرنامج (التعليمات) الذي يتم تشغيله عند تنفيذ الخيط الذي أنشأناه، لذلك يتم استخدام هذه الطريقة لحساب جدول الضرب. الكود المحدد هو كما يلي:
انسخ رمز الكود كما يلي:
@تجاوز
تشغيل الفراغ العام () {
لـ (int i = 0; i < 10; i++) {
System.out.printf("%s: %d * %d = %d/n"،
Thread.currentThread().getName(),
رقم، أنا، أنا * رقم)؛
}
}
4. الآن، حان الوقت لتنفيذ الفئة الرئيسية للتطبيق النموذجي. أنشئ فصلًا باسم Main وأضف الطريقة الرئيسية في الفصل. الرمز هو كما يلي:
انسخ رمز الكود كما يلي:
الطبقة العامة الرئيسية {
public static void main(String[] args) {
5. داخل الأسلوب main()، أنشئ حلقة for تجتاز عشر مرات في نص الحلقة، وأنشئ حاسبة كائن لفئة الحاسبة، وأنشئ مؤشر ترابط كائن لفئة Thread، وقم بتمرير الآلة الحاسبة كمعلمة للفئة. منشئ إلى بيان التهيئة. أخيرًا، قم باستدعاء أسلوب start() لكائن مؤشر الترابط. الرمز هو كما يلي:
انسخ رمز الكود كما يلي:
لـ (int i = 0; i < 10; i++) {
حاسبة الآلة الحاسبة = حاسبة جديدة (i)؛
موضوع الموضوع = موضوع جديد (آلة حاسبة)؛
Thread.start();
}
6. قم بتشغيل هذا البرنامج لترى كيفية تنفيذ المواضيع المختلفة بشكل متزامن.
أعرف لماذا
ما يلي هو جزء من الإخراج المطبوع على وحدة التحكم عند تشغيل البرنامج، يمكننا أن نرى أن جميع سلاسل الرسائل التي أنشأناها يتم تنفيذها بشكل متزامن.
انسخ رمز الكود كما يلي:
الموضوع-3: 3*5 = 15
الموضوع-0: 0 * 2 = 0
الموضوع-3: 3*6 = 18
الموضوع-1: 1 * 6 = 6
الموضوع-1: 1 * 7 = 7
الموضوع-3: 3*7 = 21
الموضوع-3: 3*8 = 24
الموضوع-0: 0 * 3 = 0
الموضوع-0: 0 * 4 = 0
الموضوع-3: 3*9 = 27
الموضوع-1: 1 * 8 = 8
تقوم جميع برامج Java بتنفيذ موضوع واحد على الأقل. عندما نقوم بتشغيل برنامج Java، سيقوم جهاز Java الظاهري (المشار إليه فيما يلي باسم JVM) بتشغيل سلسلة رسائل واستدعاء البرنامج الذي يحتوي على الطريقة الرئيسية ().
عندما يتم استدعاء أسلوب start() لكائن Thread، يتم إنشاء مؤشر ترابط آخر. كم مرة يتم استدعاء طريقة start () وعدد سلاسل الرسائل التي سيتم إنشاؤها.
عندما تنتهي جميع سلاسل العمليات من التنفيذ، سينتهي برنامج Java. (ما لم يتم تنفيذ جميع سلاسل العمليات غير الخفية ما لم تكن هناك ظروف خاصة.) عند انتهاء مؤشر ترابط البداية (مثل مؤشر الترابط الذي ينفذ الطريقة الرئيسية ())، ستستمر مؤشرات الترابط المتبقية في التنفيذ حتى تكتمل مهمة الحوسبة. عندما يستدعي أحد سلاسل العمليات System.exit()، ويطلب من JVM إنهاء البرنامج، تنهي جميع سلاسل العمليات تنفيذها.
عندما يتم استدعاء أسلوب run() لكائن Thread، لن يتم إنشاء مؤشر الترابط؛ وبالمثل، عندما يتم استدعاء أسلوب run() للفئة التي تنفذ الواجهة القابلة للتشغيل، لن يتم إنشاء مؤشر الترابط. يتم إنشاء مؤشر الترابط فقط عند استدعاء أسلوب start () لكائن Thread.
لا تنتهي أبدا
كما ذكرنا في بداية هذا القسم، هناك طريقة أخرى لإنشاء سلسلة رسائل: وراثة فئة Thread وتجاوز طريقة run() بهذه الطريقة، يمكنك إنشاء كائن من فئة Thread الفرعية ثم استدعاء start(). طريقة إنشاء الموضوع.
انسخ رمز الكود كما يلي:
لأنني كنت أستعد للمقابلة، وجدت مجموعة من المعلومات حول Java Multithreading، بما في ذلك "Java 7 Concurrency Cookbook"، والتفسيرات بسيطة للغاية وسهلة الفهم، وهي مناسبة جدًا للأصدقاء الذين لا يعرفون الكثير عن تعدد الخيوط ولكنك تريد أن تتعلمها بجدية. بعد البحث، لم أتمكن من العثور على النسخة الصينية، لذلك قررت أن أصنع ما يكفي من الطعام والملابس بنفسي. ولذلك، فإننا نخطط لنشر ترجمة غير رسمية، وسيكون العنوان مبدئيًا بعنوان "مجموعة نماذج Java7 المتزامنة".
استخدام العقيدة
تمت ترجمة هذه المقالة من "Java 7 Concurrency Cookbook" (سرقها D Gua Ge باسم "مجموعة أمثلة Java7 Concurrency") ويتم استخدامها فقط كمواد تعليمية. ولا يجوز استخدامه لأية أغراض تجارية دون تصريح.
نجاح صغير
لا يحتوي الكتاب الأصلي على الكود الكامل، وهو أمر غير مناسب للعرض. لذلك، أضاف Brother D Gua قسمًا لإظهار الإصدار الكامل للكود الموضح في هذا القسم.
الكود الكامل لفئة الحاسبة هو كما يلي:
الحزمة com.diguage.books.concurrencycookbook.chapter1.recipe1؛
/**
* التاريخ: 2013-09-13
*الزمن: 21:42
*/
تطبق حاسبة الفئة العامة Runnable {
رقم خاص؛
الحاسبة العامة (رقم int) {
this.number = number;
}
@تجاوز
تشغيل الفراغ العام () {
لـ (int i = 0; i < 10; i++) {
System.out.printf("%s: %d * %d = %d/n"،
Thread.currentThread().getName(),
رقم، أنا، أنا * رقم)؛
}
}
}
الكود الكامل للفئة الرئيسية
انسخ رمز الكود كما يلي:
الحزمة com.diguage.books.concurrencycookbook.chapter1.recipe1؛
/**
* التاريخ: 2013-09-13
*الساعة: 19:46
*/
الطبقة العامة الرئيسية {
public static void main(String[] args) {
لـ (int i = 0; i < 10; i++) {
حاسبة الآلة الحاسبة = حاسبة جديدة (i)؛
موضوع الموضوع = موضوع جديد (آلة حاسبة)؛
Thread.start();
}
}
}