1. المواضيع والعمليات
1. ما هو الفرق بين الموضوع والعملية:
يشير مؤشر ترابط إلى وحدة تنفيذ يمكنها تنفيذ رمز البرنامج أثناء التنفيذ. في لغة Java ، تحتوي المواضيع على أربع ولايات: تشغيل ، جاهزة ، تعليق وإنهاء.
تشير العملية إلى برنامج يتم تنفيذه. تصبح المواضيع أيضًا عمليات خفيفة الوزن عندما يكون لديهم ما يفعلونه. لديهم أصغر وحدة تنفيذ البرنامج. يمكن أن تحتوي العملية على عدة مؤشرات ترابط. يشارك كل مؤشر ترابط مساحة الطاقة الداخلية للبرنامج (قطاعات الكود ، شرائح البيانات ومساحة الكومة) وبعض الموارد على مستوى العملية (مثل الملفات المفتوحة) ، ولكن لكل مؤشر ترابط مساحة خاصة به.
2. لماذا تستخدم العمليات المتعددة ؟ <br /> هناك بشكل أساسي الجوانب التالية على مستوى نظام التشغيل:
- يمكن أن يؤدي استخدام متعدد الخيوط إلى تقليل وقت استجابة البرنامج. إذا كانت العملية تستغرق وقتًا طويلاً ، أو كانت عالقة في انتظار طويل ، فلن يستجيب البرنامج لعمليات مثل الماوس ولوحة المفاتيح. بعد استخدام متعدد الخيوط ، يمكن تخصيص مؤشر الترابط المستهلك للوقت لخيط منفصل للتنفيذ ، مما يجعل البرنامج أفضل من التفاعل.
- يعد إنشاء مؤشرات الترابط وتبديل النفقات العامة أقل تكلفة مقارنة بالعمليات ، في حين أن MultiThreading فعال للغاية في مشاركة البيانات.
-تتمتع أجهزة الكمبيوتر المتعددة CPU أو متعددة النواة بالقدرة على تنفيذ قواعد ثلاثية الأبعاد. إذا تم استخدام عملية واحدة ، فلن يتم إعادة استخدام موارد الكمبيوتر ، مما يؤدي إلى مضيعة كبيرة للموارد. يمكن أن يؤدي استخدام MultiThreading على أجهزة الكمبيوتر المتعددة CPU إلى تحسين استخدام وحدة المعالجة المركزية.
- يمكن أن يؤدي استخدام Multithreading إلى تبسيط بنية البرنامج وجعله من السهل فهمه وصيانته.
2. إنشاء مؤشرات ترابط <br /> هناك عمومًا ثلاث طرق للتنفيذ متعدد الخيوط ، والأولين هما أكثر الطرق شيوعًا:
1. ورث فئة الخيط وتجاوز طريقة التشغيل ()
الموضوع هو في الأساس مثيل يقوم بتنفيذ الواجهة القابلة للتشغيل. تجدر الإشارة إلى أنه بعد استدعاء طريقة START () ، لا ينفذ رمز متعدد الخيوط على الفور ، ولكن بدلاً من ذلك يجعل سلسلة الرسائل. متى يتم تحديد رمز متعدد الخيوط بواسطة نظام التشغيل.
فيما يلي الخطوات الرئيسية:
(1) تحديد الفئة الفرعية لفئة الخيط وتجاوز طريقة التشغيل للفئة. يمثل هيئة طريقة التشغيل المهمة التي يريد مؤشر الترابط إكمالها. لذلك ، تسمى طريقة التشغيل () هيئة التنفيذ.
(2) إنشاء مثيل من الفئة الفرعية لخيط ، أي إنشاء كائن مؤشر ترابط.
(3) استدعاء طريقة START () لكائن مؤشر الترابط لبدء مؤشر الترابط.
يمتد TestTreshread من الفئة العامة Thread {public void run () {system.out.println ("Hello World") ؛ } public static void main (string [] args) {thread mthread = new testthread () ؛ mthread.start () ؛ }} 2. قم بتنفيذ الواجهة القابلة للتشغيل وتنفيذ طريقة Run () للواجهة
فيما يلي الخطوات الرئيسية:
(1) تخصيص الفئة وتنفيذ واجهة Runnable ، وتنفيذ طريقة Run ().
(2) قم بإنشاء مثيل من الفئة الفرعية مؤشر ترابط وتثبيت كائن مؤشر الترابط مع الكائن الذي ينفذ الواجهة القابلة للتشغيل كمعلمة.
(3) طريقة Start () لشرط مؤشر ترابط الاتصال لبدء مؤشر الترابط.
تنفس TestRunnable من الفئة العامة runnable {public void run () {system.out.println ("Hello World") ؛ }} الفئة العامة testrunnable {public static void main (string [] args) {testRunnable MtestrUnnable = new testRunnable () ؛ موضوع mthread = مؤشر ترابط جديد (mtestrunnable) ؛ mthread.start () ؛ }} 3. قم بتنفيذ الواجهة القابلة للاتصال وتجاوز طريقة الاتصال ()
الواجهة القابلة للاتصال هي في الواقع فئة وظيفية في إطار المنفذ. تشبه الواجهة القابلة للاتصال واجهة Runnable ، ولكنها توفر وظائف أكثر قوة من Runnable ، والتي تتجلى بشكل أساسي في النقاط الثلاث التالية:
(1) يمكن أن توفر قابلة للاتصال قيمة إرجاع بعد قبول المهمة ، ولا يمكن لـ Runnable توفير هذه الوظيفة.
(2) يمكن أن تتمكن طريقة CALL () في استثناءات من الاستثناءات ، في حين أن طريقة Run () من RunNable لا يمكن أن ترمي استثناءات.
(3) يمكن تشغيل Callable الحصول على كائن مستقبلي. يمثل الكائن المستقبلي نتيجة حساب إبراهيموفيتش ، ويوفر طريقة للتحقق مما إذا كان الحساب قد اكتمل. نظرًا لأن الخيط ينتمي إلى نموذج حساب غير متزامن ، فمن المستحيل الحصول على قيمة إرجاع الوظيفة من مؤشرات الترابط الأخرى. في هذه الحالة ، يمكن استخدام المستقبل لمراقبة طريقة Call () عندما يستدعي مؤشر ترابط الهدف طريقة الاتصال (). ومع ذلك ، عندما يتم استدعاء طريقة GET () في المستقبل للحصول على النتيجة ، سيحظر الخيط الحالي ويعرف نتيجة الإرجاع لطريقة الاتصال ().
فئة عامة TestCallable {// إنشاء سلسلة رسائل فئة ثابتة فئة ثابتة myTestCallable الأدوات القابلة للاتصال {public string call () رمي الاستثناء {retun "Hello World" ؛ }} public static void main (string [] args) {myTestCallable mmyTestCallable = new MyTestCallable () ؛ ExecutorService mexecutorservice = Executors.NewSingleThreadPool () ؛ مستقبل mfuture = mexecutorservice.submit (mmyTestCallable) ؛ حاول {// في انتظار انتهاء مؤشر الترابط وإرجاع نظام النتائج. } catch (استثناء e) {E.PrintStackTrace () ؛ }}}نتيجة الإخراج للبرنامج أعلاه هي: Hello World
من بين هذه الطرق الثلاث ، يوصى بشكل عام بتنفيذ الواجهة القابلة للتشغيل. والسبب هو: أولاً ، تحدد فئة مؤشرات الترابط مجموعة متنوعة من الطرق التي يمكن إعادة كتابتها بواسطة الفئات المشتقة ، ولكن يجب إعادة كتابة طريقة Run () فقط ، والتي تدرك الوظيفة الرئيسية لهذا الموضوع ، وهي الطريقة المطلوبة أيضًا لتنفيذ الواجهة القابلة للتشغيل. ثانياً ، يجب أن يتم مورث الفصل عندما يحتاج إلى تعزيزه أو تعديله. لذلك ، إذا لم تكن هناك حاجة لتجاوز طرق أخرى لفئة مؤشرات الترابط ، فمن الأفضل تنفيذ واجهة Runnable في هذه الحالة.
3. مؤشر ترابط المقاطعة <BR /> سينتهي مؤشر الترابط عندما يقوم طريقة Run () بتنفيذ العبارة الأخيرة في هيئة الطريقة والعودة عن طريق تنفيذ بيان الإرجاع ، أو عندما لا يتم التقاط استثناء لم يتم اكتشافه في هذه الطريقة. كانت هناك طريقة توقف في الإصدارات السابقة من Java ، والتي يمكن أن تتصل بمواضيع أخرى لإنهاء مؤشر الترابط ، ولكن تم الآن إهمال هذه الطريقة.
يمكن استخدام طريقة المقاطعة لطلب إنهاء الخيط. عندما يستدعي مؤشر ترابط طريقة المقاطعة ، سيتم تعيين حالة مقاطعة مؤشر الترابط. هذا هو العلم المنطقي الذي لا يوجد لديه خيط. يجب على كل مؤشر ترابط التحقق من هذه العلامة من وقت لآخر لتحديد ما إذا كان مؤشر الترابط قد توقف.
لمعرفة ما إذا تم تعيين مؤشر الترابط ، يمكنك الاتصال على Thread.currentThread (). IsInterrupted ():
بينما (! thread.currentTherve ()
ومع ذلك ، إذا تم حظر خيط ، فلا يمكن اكتشاف حالة المقاطعة. هذا هو المكان الذي يتم فيه إنشاء مقاطع. عندما يتم استدعاء طريقة المقاطعة على موضوع محظور (يسمى النوم أو الانتظار). ستتم مقاطعة مكالمة الحظر من قبل المقاطع.
إذا تم استدعاء طريقة النوم (أو غيرها من طريقة المقاطعة) بعد كل تكرار ، فإن الكشف المقطوع غير ضروري وغير ضروري. إذا تم استدعاء طريقة النوم عند ضبط حالة المقاطعة ، فلن تنام ، بل ستزيل الحالة وتلقي على سبيل المثال. لذلك إذا قمت بالاتصال بالنوم في حلقة ، فلا تكتشف حالة المقاطعة ، فما عليك سوى التقاط المقاطع.
في العديد من الرموز المنشورة ، ستجد أن InterruptedException يتم قمعها بمستوى منخفض للغاية:
void mytask () {... حاول {Sleep (50)} catch (InterruptedException e) {...}}لا تفعل هذا. إذا كنت لا تعتقد أن هناك أي فائدة في الصيد ، فهناك خياران معقولان:
استدعاء thread.currentThRead (). interrup () في الصيد لتعيين حالة المقاطعة. يمكن للمتصلين اكتشاف ذلك. الخيار الأفضل هو استخدام Throw InterruptedException لتمييز طريقتك ، دون استخدام كتل عبارات Try لالتقاط واحدة مكتملة. بهذه الطريقة يمكن للمتصل التقاط هذا الاستثناء:
void mytask () رمي interruptedException {sleep (50)}4. حالة الموضوع
(1). حالة جديدة (جديدة): يتم إنشاء كائن مؤشر ترابط جديد.
(2). حالة جاهزة (RunNable): بعد إنشاء كائن مؤشر الترابط ، تقوم مؤشرات الترابط الأخرى بتسمية طريقة START () للكائن. يقع الخيط في هذه الحالة في مجموعة الخيوط القابلة للتشغيل وتصبح قابلة للتشغيل ، في انتظار الحصول على حقوق استخدام وحدة المعالجة المركزية.
(3). حالة التشغيل: يحصل مؤشر الترابط في الحالة الجاهزة على وحدة المعالجة المركزية وتنفيذ رمز البرنامج.
(4). الحالة المحظورة: تعني الحالة المحظورة أن الخيط يتخلى عن حقوق استخدام وحدة المعالجة المركزية لسبب ما ويتوقف مؤقتًا عن الجري. ليس حتى يدخل الخيط إلى الحالة الجاهزة أن لديها فرصة للذهاب إلى حالة الجري. هناك ثلاثة أنواع من الانسداد:
- في انتظار الحظر: يقوم سلسلة التشغيل بتنفيذ طريقة Wait () ، وسيضع JVM الخيط في تجمع الانتظار.
- حظر متزامن: عندما يكتسب مؤشر ترابط التشغيل قفل تزامن الكائن ، إذا كان قفل المزامنة يشغله مؤشرات ترابط أخرى ، فإن JVM سيضع الخيط في تجمع القفل.
- حظر آخر: عندما ينفذ مؤشر ترابط تشغيل Sleep () أو join () ، أو يصدر طلب I/O ، سيقوم JVM بتعيين الخيط على حالة الحظر. عندما تم توقيت Sleep () ، انتظرت الانضمام () لإنهاء الخيط أو توقيته ، أو تم الانتهاء من معالجة الإدخال/الإخراج ، حيث تم إعادة إدخال الخيط إلى الحالة الجاهزة.
(5). Dead State: انتهى الخيط من تنفيذ أو الخروج من طريقة Run () بسبب استثناء ، وينهي الخيط دورة حياته.
5. أولوية الخيط وخيط الخفي
1. أولوية الموضوع
في Java ، يكون لكل مؤشر ترابط أولوية ، وبشكل افتراضي ، يرث مؤشر ترابط أولوية فئة الأم. يمكنك استخدام طريقة setPriority لزيادة أو تقليل أي أولوية مؤشر ترابط. يمكن ضبط الأولوية على أي قيمة بين min_priority (المعرّفة على أنها 1 في فئة الخيط) و max_priority (المعرّفة على أنها 10 في فئة الخيط). الأولوية الافتراضية للمواضيع هي norm_priority (المعرّفة على أنها 5 في فئة مؤشر الترابط).
حاول ألا تعتمد على الأولوية. إذا كنت ترغب حقًا في استخدامه ، فيجب عليك تجنب الخطأ الشائع الذي يرتكبه المبتدئون. إذا لم تدخل العديد من مؤشرات الترابط ذات الأولوية العالية في الحالة غير النشطة ، فقد لا يتم تنفيذ مؤشرات الترابط ذات الأولوية المنخفضة. عندما يقرر المجدول تشغيل مؤشر ترابط جديد ، فإنه يختار أولاً بين مؤشرات الترابط ذات الأولوية ، على الرغم من أن هذا سيؤدي إلى تجويع مؤشرات الترابط ذات الأولوية المنخفضة تمامًا.
2. خيط الخفي
استدعاء setdaemon (صواب) ؛ يحول الخيط إلى موضوع خفي. الغرض الوحيد من خيوط الخفي هو توفير الخدمات لخيوط أخرى. موضوع التوقيت هو مثال. يرسل إشارات إلى مؤشرات ترابط أخرى بانتظام أو مسح مؤشرات الترابط القديمة التي تخبر عناصر ذاكرة التخزين المؤقت. عند ترك خيوط الخفي فقط ، يخرج الجهاز الظاهري ، لأنه إذا تم ترك مؤشرات الترابط الخفي فقط ، فلا داعي للمواصلة تشغيل البرنامج.
بالإضافة إلى ذلك ، فإن مجموعة القمامة JVM وإدارة الذاكرة وغيرها من المواضيع الخفي هي مؤشرات ترابط الخفي. أيضًا ، عند القيام بتطبيقات قاعدة البيانات ، يحتوي تجمع اتصال قاعدة البيانات المستخدم أيضًا على العديد من مؤشرات الترابط الخلفية ، ومراقبة عدد الاتصالات ، ووقت المهلة ، والحالة ، إلخ.
ما سبق يدور حول تعريف الخيط وحالة وخصائص Java MultiThreading. آمل أن يكون ذلك مفيدًا لتعلم الجميع.